diff --git a/.codex/config.toml b/.codex/config.toml new file mode 100644 index 00000000..2c247f3c --- /dev/null +++ b/.codex/config.toml @@ -0,0 +1,25 @@ +[mcp_servers.github-mcp-server] +command = "docker" +args = [ "run", "-i", "--rm", "-e", "GITHUB_DYNAMIC_TOOLSETS", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN", "-e", "GITHUB_TOOLSETS", "ghcr.io/github/github-mcp-server",] +id = "ab12cd34-5678-90ef-1234-567890abcdef" + +[mcp_servers.notion-mcp-server] +command = "npx" +args = [ "-y", "@notionhq/notion-mcp-server@1.8.1", "--transport", "stdio", "--port", "3000", "secret_notion_token_67890",] +id = "8b9c1d20-2345-6789-abcd-ef0123456789" + +[mcp_servers.test-docker-server] +command = "docker" +args = [ "run", "-i", "--rm", "example/test-server", "--verbose", "--config", "-e", "TEST_TOKEN", "/app/config.json",] +id = "test-docker-with-pkg-args" + +[mcp_servers.github-mcp-server.env] +GITHUB_PERSONAL_ACCESS_TOKEN = "ghp_token_123" +GITHUB_TOOLSETS = "context" +GITHUB_DYNAMIC_TOOLSETS = "1" + +[mcp_servers.notion-mcp-server.env] +NOTION_TOKEN = "secret_notion_token_67890" + +[mcp_servers.test-docker-server.env] +TEST_TOKEN = "test_token_value" diff --git a/src/apm_cli/core/target_detection.py b/src/apm_cli/core/target_detection.py index 6e4ca9c1..d29668c4 100644 --- a/src/apm_cli/core/target_detection.py +++ b/src/apm_cli/core/target_detection.py @@ -8,7 +8,8 @@ 1. Explicit --target flag (always wins) 2. apm.yml target setting (top-level field) 3. Auto-detect from existing folders: - - .github/ only -> copilot (internal: "vscode") + - .github/ only -> minimal (ambiguous; .github/ is too common for CI + to reliably infer Copilot — user should set target explicitly) - .claude/ only -> claude - .cursor/ only -> cursor - .opencode/ only -> opencode @@ -86,6 +87,12 @@ def agents_alias_was_detected() -> bool: # instead of substring matching. REASON_NO_TARGET_FOLDER = "no target folder found" +# Detection reason returned by detect_target() when only .github/ exists but +# no explicit or config target is set. .github/ is too common (CI workflows, +# issue templates, CODEOWNERS) to reliably infer Copilot usage — treat it as +# ambiguous and ask the user to declare their target explicitly. +REASON_AMBIGUOUS_GITHUB = "ambiguous .github/ — set target in apm.yml or use --target" + # User-facing target values (includes aliases accepted by CLI) UserTargetType = Literal[ "copilot", @@ -189,7 +196,10 @@ def detect_target( # noqa: PLR0911 if len(detected) >= 2: return "all", f"detected {' and '.join(detected)} folders" elif github_exists: - return "vscode", "detected .github/ folder" + # .github/ alone is too ambiguous to infer Copilot — most repos have + # it for CI workflows, issue templates, CODEOWNERS, etc. Return + # minimal so the user is prompted to set target explicitly. + return "minimal", REASON_AMBIGUOUS_GITHUB elif claude_exists: return "claude", "detected .claude/ folder" elif cursor_exists: diff --git a/tests/unit/core/test_target_detection.py b/tests/unit/core/test_target_detection.py index d94d840c..3c124ee0 100644 --- a/tests/unit/core/test_target_detection.py +++ b/tests/unit/core/test_target_detection.py @@ -124,8 +124,8 @@ def test_config_target_all(self, tmp_path): assert target == "all" assert reason == "apm.yml target" - def test_auto_detect_github_only(self, tmp_path): - """Auto-detect vscode when only .github/ exists.""" + def test_auto_detect_github_only_returns_minimal(self, tmp_path): + """Auto-detect minimal when only .github/ exists (ambiguous).""" (tmp_path / ".github").mkdir() target, reason = detect_target( @@ -134,8 +134,8 @@ def test_auto_detect_github_only(self, tmp_path): config_target=None, ) - assert target == "vscode" - assert "detected .github/ folder" in reason + assert target == "minimal" + assert "ambiguous" in reason def test_auto_detect_claude_only(self, tmp_path): """Auto-detect claude when only .claude/ exists.""" @@ -176,6 +176,63 @@ def test_auto_detect_neither_folder(self, tmp_path): assert "no target folder found" in reason +class TestDetectTargetAmbiguousGithub: + """Tests for .github/-only auto-detection returning minimal (ambiguous).""" + + def test_github_only_returns_minimal(self, tmp_path): + """Only .github/ present — too ambiguous to assume Copilot.""" + (tmp_path / ".github").mkdir() + target, reason = detect_target(project_root=tmp_path) + assert target == "minimal" + assert "ambiguous" in reason + + def test_github_only_reason_mentions_set_target(self, tmp_path): + """Reason message should guide user to set target explicitly.""" + (tmp_path / ".github").mkdir() + _, reason = detect_target(project_root=tmp_path) + assert "apm.yml" in reason or "--target" in reason + + def test_github_only_explicit_copilot_wins(self, tmp_path): + """Explicit --target copilot overrides ambiguous .github/ detection.""" + (tmp_path / ".github").mkdir() + target, reason = detect_target( + project_root=tmp_path, explicit_target="copilot" + ) + assert target == "vscode" + assert "explicit" in reason + + def test_github_only_config_copilot_wins(self, tmp_path): + """Config target: copilot overrides ambiguous .github/ detection.""" + (tmp_path / ".github").mkdir() + target, reason = detect_target( + project_root=tmp_path, config_target="copilot" + ) + assert target == "vscode" + assert "apm.yml" in reason + + def test_github_plus_claude_returns_all(self, tmp_path): + """Multiple folders (.github/ + .claude/) still returns all.""" + (tmp_path / ".github").mkdir() + (tmp_path / ".claude").mkdir() + target, reason = detect_target(project_root=tmp_path) + assert target == "all" + assert ".github/" in reason and ".claude/" in reason + + def test_github_plus_cursor_returns_all(self, tmp_path): + """Multiple folders (.github/ + .cursor/) still returns all.""" + (tmp_path / ".github").mkdir() + (tmp_path / ".cursor").mkdir() + target, _ = detect_target(project_root=tmp_path) + assert target == "all" + + def test_reason_ambiguous_constant_defined(self): + """REASON_AMBIGUOUS_GITHUB is importable and non-empty.""" + from apm_cli.core.target_detection import REASON_AMBIGUOUS_GITHUB + + assert REASON_AMBIGUOUS_GITHUB + assert "ambiguous" in REASON_AMBIGUOUS_GITHUB + + class TestShouldCompileAgentsMd: """Tests for should_compile_agents_md function."""