From 832773dbaca59b68dfbe7ac70c3a21c151322d09 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 18 Jun 2026 11:34:20 +0800 Subject: [PATCH 1/3] chore: sync issue template agent lists --- .github/ISSUE_TEMPLATE/agent_request.yml | 2 +- .github/ISSUE_TEMPLATE/bug_report.yml | 39 ++++++--- .github/ISSUE_TEMPLATE/feature_request.yml | 39 ++++++--- tests/test_agent_config_consistency.py | 92 ++++++++++++++++++++++ 4 files changed, 147 insertions(+), 25 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/agent_request.yml b/.github/ISSUE_TEMPLATE/agent_request.yml index 1a44adec2d..e81b5f0433 100644 --- a/.github/ISSUE_TEMPLATE/agent_request.yml +++ b/.github/ISSUE_TEMPLATE/agent_request.yml @@ -8,7 +8,7 @@ body: value: | Thanks for requesting a new agent! Before submitting, please check if the agent is already supported. - **Currently supported agents**: Claude Code, Gemini CLI, GitHub Copilot, Cursor, Qwen Code, opencode, Codex CLI, Windsurf, Kilo Code, Auggie CLI, Roo Code, CodeBuddy, Qoder CLI, Kiro CLI, Amp, SHAI, Tabnine CLI, Antigravity, IBM Bob, Mistral Vibe, Kimi Code, Trae, Pi Coding Agent, iFlow CLI, Devin for Terminal + **Currently supported agents**: Amp, Antigravity, Auggie CLI, Claude Code, Cline, CodeBuddy, Codex CLI, Cursor, Devin for Terminal, Forge, Gemini CLI, GitHub Copilot, Goose, Hermes Agent, IBM Bob, iFlow CLI, Junie, Kilo Code, Kimi Code, Kiro CLI, Lingma, Mistral Vibe, opencode, Pi Coding Agent, Qoder CLI, Qwen Code, Roo Code, RovoDev ACLI, SHAI, Tabnine CLI, Trae, Windsurf, Zed - type: input id: agent-name diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index dd09f8e02a..374bc7b591 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -62,24 +62,39 @@ body: label: AI Agent description: Which AI agent are you using? options: + - Amp + - Antigravity + - Auggie CLI - Claude Code + - Cline + - CodeBuddy + - Codex CLI + - Cursor + - Devin for Terminal + - Forge - Gemini CLI - GitHub Copilot - - Cursor - - Qwen Code - - opencode - - Codex CLI - - Windsurf + - Goose + - Hermes Agent + - IBM Bob + - iFlow CLI + - Junie - Kilo Code - - Auggie CLI - - Roo Code - - CodeBuddy - - Qoder CLI + - Kimi Code - Kiro CLI - - Amp + - Lingma + - Mistral Vibe + - opencode + - Pi Coding Agent + - Qoder CLI + - Qwen Code + - Roo Code + - RovoDev ACLI - SHAI - - IBM Bob - - Antigravity + - Tabnine CLI + - Trae + - Windsurf + - Zed - Not applicable validations: required: true diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index 3b5889288b..8ccee27fd4 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -56,24 +56,39 @@ body: description: Does this feature relate to a specific AI agent? options: - All agents + - Amp + - Antigravity + - Auggie CLI - Claude Code + - Cline + - CodeBuddy + - Codex CLI + - Cursor + - Devin for Terminal + - Forge - Gemini CLI - GitHub Copilot - - Cursor - - Qwen Code - - opencode - - Codex CLI - - Windsurf + - Goose + - Hermes Agent + - IBM Bob + - iFlow CLI + - Junie - Kilo Code - - Auggie CLI - - Roo Code - - CodeBuddy - - Qoder CLI + - Kimi Code - Kiro CLI - - Amp + - Lingma + - Mistral Vibe + - opencode + - Pi Coding Agent + - Qoder CLI + - Qwen Code + - Roo Code + - RovoDev ACLI - SHAI - - IBM Bob - - Antigravity + - Tabnine CLI + - Trae + - Windsurf + - Zed - Not applicable - type: textarea diff --git a/tests/test_agent_config_consistency.py b/tests/test_agent_config_consistency.py index 1176009778..36e88ac833 100644 --- a/tests/test_agent_config_consistency.py +++ b/tests/test_agent_config_consistency.py @@ -2,15 +2,107 @@ from pathlib import Path +import yaml + from specify_cli import AGENT_CONFIG from specify_cli.extensions import CommandRegistrar REPO_ROOT = Path(__file__).resolve().parent.parent +ISSUE_TEMPLATE_AGENT_KEYS = [ + "amp", + "agy", + "auggie", + "claude", + "cline", + "codebuddy", + "codex", + "cursor-agent", + "devin", + "forge", + "gemini", + "copilot", + "goose", + "hermes", + "bob", + "iflow", + "junie", + "kilocode", + "kimi", + "kiro-cli", + "lingma", + "vibe", + "opencode", + "pi", + "qodercli", + "qwen", + "roo", + "rovodev", + "shai", + "tabnine", + "trae", + "windsurf", + "zed", +] + +ISSUE_TEMPLATE_AGENT_NAMES = [ + AGENT_CONFIG[key]["name"] for key in ISSUE_TEMPLATE_AGENT_KEYS +] + + +def _issue_template(path: str) -> dict: + return yaml.safe_load((REPO_ROOT / path).read_text(encoding="utf-8")) + + +def _body_item_by_id(template: dict, item_id: str) -> dict: + for item in template["body"]: + if item.get("id") == item_id: + return item + raise AssertionError(f"Expected issue template body item {item_id!r}") + + +def _dropdown_options(path: str, item_id: str) -> list[str]: + item = _body_item_by_id(_issue_template(path), item_id) + return item["attributes"]["options"] + class TestAgentConfigConsistency: """Ensure kiro-cli migration stays synchronized across key surfaces.""" + def test_issue_template_agent_lists_match_runtime_integrations(self): + """GitHub issue templates should list all concrete built-in agents.""" + concrete_agent_keys = set(AGENT_CONFIG) - {"generic"} + + assert set(ISSUE_TEMPLATE_AGENT_KEYS) == concrete_agent_keys + assert len(ISSUE_TEMPLATE_AGENT_KEYS) == len(concrete_agent_keys) + assert "Generic (bring your own agent)" not in ISSUE_TEMPLATE_AGENT_NAMES + + bug_options = _dropdown_options( + ".github/ISSUE_TEMPLATE/bug_report.yml", + "ai-agent", + ) + assert bug_options == ISSUE_TEMPLATE_AGENT_NAMES + ["Not applicable"] + + feature_options = _dropdown_options( + ".github/ISSUE_TEMPLATE/feature_request.yml", + "ai-agent", + ) + assert feature_options == [ + "All agents", + *ISSUE_TEMPLATE_AGENT_NAMES, + "Not applicable", + ] + + agent_request = _issue_template( + ".github/ISSUE_TEMPLATE/agent_request.yml" + ) + supported_agents_text = agent_request["body"][0]["attributes"]["value"] + assert ( + f"**Currently supported agents**: " + f"{', '.join(ISSUE_TEMPLATE_AGENT_NAMES)}" + in supported_agents_text + ) + def test_runtime_config_uses_kiro_cli_and_removes_q(self): """AGENT_CONFIG should include kiro-cli and exclude legacy q.""" assert "kiro-cli" in AGENT_CONFIG From d0c48dbc3f0d72764e3c6644f3edcd72527db2cc Mon Sep 17 00:00:00 2001 From: root Date: Mon, 22 Jun 2026 11:57:03 +0800 Subject: [PATCH 2/3] test: harden agent template consistency check --- tests/test_agent_config_consistency.py | 31 +++++++++++++++++++++----- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/tests/test_agent_config_consistency.py b/tests/test_agent_config_consistency.py index 36e88ac833..9961d66418 100644 --- a/tests/test_agent_config_consistency.py +++ b/tests/test_agent_config_consistency.py @@ -66,8 +66,24 @@ def _dropdown_options(path: str, item_id: str) -> list[str]: return item["attributes"]["options"] +def _normalized_markdown(text: str) -> str: + return " ".join(text.split()) + + +def _markdown_value_containing(path: str, marker: str) -> str: + template = _issue_template(path) + normalized_marker = _normalized_markdown(marker) + for item in template["body"]: + if item.get("type") != "markdown": + continue + value = item["attributes"]["value"] + if normalized_marker in _normalized_markdown(value): + return value + raise AssertionError(f"Expected issue template markdown containing {marker!r}") + + class TestAgentConfigConsistency: - """Ensure kiro-cli migration stays synchronized across key surfaces.""" + """Ensure agent configuration stays synchronized across key surfaces.""" def test_issue_template_agent_lists_match_runtime_integrations(self): """GitHub issue templates should list all concrete built-in agents.""" @@ -93,14 +109,17 @@ def test_issue_template_agent_lists_match_runtime_integrations(self): "Not applicable", ] - agent_request = _issue_template( - ".github/ISSUE_TEMPLATE/agent_request.yml" + supported_agents_text = _markdown_value_containing( + ".github/ISSUE_TEMPLATE/agent_request.yml", + "**Currently supported agents**:", ) - supported_agents_text = agent_request["body"][0]["attributes"]["value"] - assert ( + expected_supported_agents = ( f"**Currently supported agents**: " f"{', '.join(ISSUE_TEMPLATE_AGENT_NAMES)}" - in supported_agents_text + ) + assert ( + _normalized_markdown(expected_supported_agents) + in _normalized_markdown(supported_agents_text) ) def test_runtime_config_uses_kiro_cli_and_removes_q(self): From 11dbb520c11f20c69846c24f7ed9e360f3809ef3 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 23 Jun 2026 10:14:14 +0800 Subject: [PATCH 3/3] test: harden agent template drift checks --- .github/ISSUE_TEMPLATE/agent_request.yml | 2 +- .github/ISSUE_TEMPLATE/bug_report.yml | 1 + .github/ISSUE_TEMPLATE/feature_request.yml | 1 + tests/test_agent_config_consistency.py | 69 ++++++++++++++++------ 4 files changed, 53 insertions(+), 20 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/agent_request.yml b/.github/ISSUE_TEMPLATE/agent_request.yml index e81b5f0433..f72491dff7 100644 --- a/.github/ISSUE_TEMPLATE/agent_request.yml +++ b/.github/ISSUE_TEMPLATE/agent_request.yml @@ -8,7 +8,7 @@ body: value: | Thanks for requesting a new agent! Before submitting, please check if the agent is already supported. - **Currently supported agents**: Amp, Antigravity, Auggie CLI, Claude Code, Cline, CodeBuddy, Codex CLI, Cursor, Devin for Terminal, Forge, Gemini CLI, GitHub Copilot, Goose, Hermes Agent, IBM Bob, iFlow CLI, Junie, Kilo Code, Kimi Code, Kiro CLI, Lingma, Mistral Vibe, opencode, Pi Coding Agent, Qoder CLI, Qwen Code, Roo Code, RovoDev ACLI, SHAI, Tabnine CLI, Trae, Windsurf, Zed + **Currently supported agents**: Amp, Antigravity, Auggie CLI, Claude Code, Cline, CodeBuddy, Codex CLI, Cursor, Devin for Terminal, Forge, Gemini CLI, GitHub Copilot, Goose, Hermes Agent, IBM Bob, iFlow CLI, Junie, Kilo Code, Kimi Code, Kiro CLI, Lingma, Mistral Vibe, opencode, Pi Coding Agent, Qoder CLI, Qwen Code, Roo Code, RovoDev ACLI, SHAI, Tabnine CLI, Trae, Windsurf, ZCode, Zed - type: input id: agent-name diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 374bc7b591..c1e1dc572c 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -94,6 +94,7 @@ body: - Tabnine CLI - Trae - Windsurf + - ZCode - Zed - Not applicable validations: diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index 8ccee27fd4..3d55c0442c 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -88,6 +88,7 @@ body: - Tabnine CLI - Trae - Windsurf + - ZCode - Zed - Not applicable diff --git a/tests/test_agent_config_consistency.py b/tests/test_agent_config_consistency.py index 9961d66418..ed16625d33 100644 --- a/tests/test_agent_config_consistency.py +++ b/tests/test_agent_config_consistency.py @@ -1,5 +1,6 @@ """Consistency checks for agent configuration across runtime surfaces.""" +import re from pathlib import Path import yaml @@ -42,13 +43,10 @@ "tabnine", "trae", "windsurf", + "zcode", "zed", ] -ISSUE_TEMPLATE_AGENT_NAMES = [ - AGENT_CONFIG[key]["name"] for key in ISSUE_TEMPLATE_AGENT_KEYS -] - def _issue_template(path: str) -> dict: return yaml.safe_load((REPO_ROOT / path).read_text(encoding="utf-8")) @@ -82,22 +80,63 @@ def _markdown_value_containing(path: str, marker: str) -> str: raise AssertionError(f"Expected issue template markdown containing {marker!r}") +def _markdown_paragraph_containing(path: str, marker: str) -> str: + value = _markdown_value_containing(path, marker) + normalized_marker = _normalized_markdown(marker) + for paragraph in re.split(r"\n\s*\n", value): + if normalized_marker in _normalized_markdown(paragraph): + return paragraph + raise AssertionError(f"Expected issue template paragraph containing {marker!r}") + + +def _supported_agent_names_from_agent_request_template() -> list[str]: + marker = "**Currently supported agents**:" + paragraph = _markdown_paragraph_containing( + ".github/ISSUE_TEMPLATE/agent_request.yml", + marker, + ) + supported_agents_text = _normalized_markdown(paragraph).split(marker, 1)[1].strip() + return [agent.strip() for agent in supported_agents_text.split(",")] + + class TestAgentConfigConsistency: """Ensure agent configuration stays synchronized across key surfaces.""" def test_issue_template_agent_lists_match_runtime_integrations(self): """GitHub issue templates should list all concrete built-in agents.""" concrete_agent_keys = set(AGENT_CONFIG) - {"generic"} + issue_template_agent_keys = set(ISSUE_TEMPLATE_AGENT_KEYS) + + missing_agent_keys = sorted(concrete_agent_keys - issue_template_agent_keys) + unexpected_agent_keys = sorted(issue_template_agent_keys - concrete_agent_keys) + duplicate_agent_keys = sorted( + key + for key in issue_template_agent_keys + if ISSUE_TEMPLATE_AGENT_KEYS.count(key) > 1 + ) + assert not missing_agent_keys, ( + "Issue template agent list is missing AGENT_CONFIG keys: " + f"{missing_agent_keys}" + ) + assert not unexpected_agent_keys, ( + "Issue template agent list includes unknown AGENT_CONFIG keys: " + f"{unexpected_agent_keys}" + ) + assert not duplicate_agent_keys, ( + "Issue template agent list contains duplicate keys: " + f"{duplicate_agent_keys}" + ) - assert set(ISSUE_TEMPLATE_AGENT_KEYS) == concrete_agent_keys - assert len(ISSUE_TEMPLATE_AGENT_KEYS) == len(concrete_agent_keys) - assert "Generic (bring your own agent)" not in ISSUE_TEMPLATE_AGENT_NAMES + issue_template_agent_names = [ + AGENT_CONFIG[key]["name"] for key in ISSUE_TEMPLATE_AGENT_KEYS + ] + assert "Generic (bring your own agent)" not in issue_template_agent_names bug_options = _dropdown_options( ".github/ISSUE_TEMPLATE/bug_report.yml", "ai-agent", ) - assert bug_options == ISSUE_TEMPLATE_AGENT_NAMES + ["Not applicable"] + assert bug_options == issue_template_agent_names + ["Not applicable"] feature_options = _dropdown_options( ".github/ISSUE_TEMPLATE/feature_request.yml", @@ -105,21 +144,13 @@ def test_issue_template_agent_lists_match_runtime_integrations(self): ) assert feature_options == [ "All agents", - *ISSUE_TEMPLATE_AGENT_NAMES, + *issue_template_agent_names, "Not applicable", ] - supported_agents_text = _markdown_value_containing( - ".github/ISSUE_TEMPLATE/agent_request.yml", - "**Currently supported agents**:", - ) - expected_supported_agents = ( - f"**Currently supported agents**: " - f"{', '.join(ISSUE_TEMPLATE_AGENT_NAMES)}" - ) assert ( - _normalized_markdown(expected_supported_agents) - in _normalized_markdown(supported_agents_text) + _supported_agent_names_from_agent_request_template() + == issue_template_agent_names ) def test_runtime_config_uses_kiro_cli_and_removes_q(self):