From 17fe1fe72cef79333f998d68e9e9efde97a43b94 Mon Sep 17 00:00:00 2001 From: JNHFlow21 Date: Tue, 11 Aug 2026 22:17:32 -0400 Subject: [PATCH] release: prepare Agent Switch 0.3.0 --- CHANGELOG.md | 19 +++++++++++++++++++ CITATION.cff | 4 ++-- README.md | 4 ++-- README.zh-CN.md | 4 ++-- VERSION | 2 +- .../AgentSwitch.xcodeproj/project.pbxproj | 4 ++-- .../AgentSwitch/Resources/L10n.swift | 2 +- pyproject.toml | 2 +- src/agent_switch/__init__.py | 2 +- src/agent_switch/mcp/bird_server.py | 2 +- src/agent_switch/mcp/xcli_server.py | 2 +- .../test_reconcile_fixture_home.py | 14 +++++++------- tests/test_config_and_secrets.py | 5 +++-- 13 files changed, 43 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 74ef00e..decacb8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,25 @@ All notable changes to Agent Switch are documented here. +## 0.3.0 - 2026-08-11 + +### Added + +- Complete English and Simplified Chinese native-app localization catalogs. +- Real, sanitized product visuals and privacy-safe repository activity graphics. +- Project metadata for software citation and answer-engine discovery. + +### Changed + +- Homebrew is now the canonical stranger-first install and update path. +- README onboarding, trust boundaries, recovery guidance, and bilingual parity were refreshed. +- Test credentials now use unmistakably synthetic, non-provider-shaped fixture values. + +### Security + +- Repository metrics keep owner-only Traffic collection inside GitHub Actions and publish only a generated aggregate image. +- Release guidance continues to disclose ad-hoc signing and the absence of Apple notarization. + ## 0.2.0 - 2026-07-23 ### Added diff --git a/CITATION.cff b/CITATION.cff index c83812b..ef4dcf3 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -7,8 +7,8 @@ authors: repository-code: "https://github.com/JNHFlow21/agent-switch" url: "https://github.com/JNHFlow21/agent-switch" license: MIT -version: 0.2.0 -date-released: 2026-07-26 +version: 0.3.0 +date-released: 2026-08-11 keywords: - MCP - macOS diff --git a/README.md b/README.md index 72bf9b3..5afa38e 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ credential store, and deterministic per-agent projections. > Agent Switch is **alpha software**. The public app is ad-hoc signed and is not > Apple-notarized. The project-owned Homebrew Cask therefore removes Gatekeeper > quarantine after installation. Review the [public source](https://github.com/JNHFlow21/agent-switch) -> and [release checksums](https://github.com/JNHFlow21/agent-switch/releases/tag/v0.2.0) +> and [release checksums](https://github.com/JNHFlow21/agent-switch/releases/tag/v0.3.0) > before installing. The native app follows the macOS language preference and ships complete @@ -77,7 +77,7 @@ Homebrew: Expected first result: ```text -agent-switch --version -> agent-switch 0.2.0 +agent-switch --version -> agent-switch 0.3.0 Native app -> /Applications/Agent Switch.app ``` diff --git a/README.zh-CN.md b/README.zh-CN.md index 6782b65..4b298c3 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -44,7 +44,7 @@ Agent Switch 用一个本地 MCP 注册表、一个私密凭据存储和可重 > Agent Switch 目前仍是 **Alpha 软件**。公开 App 使用 ad-hoc 签名,尚未经过 > Apple 公证,因此项目自己的 Homebrew Cask 会在安装完成后移除 Gatekeeper > quarantine。安装前请先检查[公开源码](https://github.com/JNHFlow21/agent-switch) -> 和[发行校验和](https://github.com/JNHFlow21/agent-switch/releases/tag/v0.2.0)。 +> 和[发行校验和](https://github.com/JNHFlow21/agent-switch/releases/tag/v0.3.0)。 原生应用会跟随 macOS 的语言偏好,并完整提供**英文**与**简体中文**界面。 @@ -74,7 +74,7 @@ Homebrew 会: 首次安装成功后应当看到: ```text -agent-switch --version -> agent-switch 0.2.0 +agent-switch --version -> agent-switch 0.3.0 原生应用 -> /Applications/Agent Switch.app ``` diff --git a/VERSION b/VERSION index 0ea3a94..0d91a54 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.2.0 +0.3.0 diff --git a/macos-app/AgentSwitch/AgentSwitch.xcodeproj/project.pbxproj b/macos-app/AgentSwitch/AgentSwitch.xcodeproj/project.pbxproj index 4d281d5..719942c 100644 --- a/macos-app/AgentSwitch/AgentSwitch.xcodeproj/project.pbxproj +++ b/macos-app/AgentSwitch/AgentSwitch.xcodeproj/project.pbxproj @@ -363,7 +363,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 0.2.0; + MARKETING_VERSION = 0.3.0; PRODUCT_BUNDLE_IDENTIFIER = com.jnhflow.AgentSwitch; PRODUCT_NAME = "Agent Switch"; SWIFT_EMIT_LOC_STRINGS = YES; @@ -388,7 +388,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 0.2.0; + MARKETING_VERSION = 0.3.0; PRODUCT_BUNDLE_IDENTIFIER = com.jnhflow.AgentSwitch; PRODUCT_NAME = "Agent Switch"; SWIFT_EMIT_LOC_STRINGS = YES; diff --git a/macos-app/AgentSwitch/AgentSwitch/Resources/L10n.swift b/macos-app/AgentSwitch/AgentSwitch/Resources/L10n.swift index 119a30e..183961b 100644 --- a/macos-app/AgentSwitch/AgentSwitch/Resources/L10n.swift +++ b/macos-app/AgentSwitch/AgentSwitch/Resources/L10n.swift @@ -6,7 +6,7 @@ import Foundation enum AppVersion { - static let current = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? "0.2.0" + static let current = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? "0.3.0" } enum L10n { diff --git a/pyproject.toml b/pyproject.toml index 4f86e78..1fafdd4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "agent-switch" -version = "0.2.0" +version = "0.3.0" description = "Local control plane for AI agents, MCP servers, Skills, CLI tools, and secrets." readme = "README.md" license = {file = "LICENSE"} diff --git a/src/agent_switch/__init__.py b/src/agent_switch/__init__.py index 326f284..20727f8 100644 --- a/src/agent_switch/__init__.py +++ b/src/agent_switch/__init__.py @@ -1,3 +1,3 @@ """Agent Switch runtime package.""" -__version__ = "0.2.0" +__version__ = "0.3.0" diff --git a/src/agent_switch/mcp/bird_server.py b/src/agent_switch/mcp/bird_server.py index 85fee7d..56a1601 100644 --- a/src/agent_switch/mcp/bird_server.py +++ b/src/agent_switch/mcp/bird_server.py @@ -53,7 +53,7 @@ def build_server() -> StdioMCPServer: string_arg = {"type": "string"} return StdioMCPServer( name="agent-birdread", - version="0.2.0", + version="0.3.0", tools=[ Tool( name="read_x_post", diff --git a/src/agent_switch/mcp/xcli_server.py b/src/agent_switch/mcp/xcli_server.py index 9d8869e..f13ae2e 100644 --- a/src/agent_switch/mcp/xcli_server.py +++ b/src/agent_switch/mcp/xcli_server.py @@ -47,7 +47,7 @@ def build_server() -> StdioMCPServer: string_arg = {"type": "string"} return StdioMCPServer( name="agent-xurl-fallback", - version="0.2.0", + version="0.3.0", tools=[ Tool( name="x_api_get_post", diff --git a/tests/integration/test_reconcile_fixture_home.py b/tests/integration/test_reconcile_fixture_home.py index 14dd6bd..20c8631 100644 --- a/tests/integration/test_reconcile_fixture_home.py +++ b/tests/integration/test_reconcile_fixture_home.py @@ -47,13 +47,13 @@ def test_reconcile_converges_and_second_run_is_idempotent(self) -> None: paths.secrets_file.write_text( "\n".join( [ - "TAVILY_API_KEY=sk-secret000000000000", - "XCRAWL_API_KEY=sk-secret000000000001", - "BIRDREAD_API_KEY=sk-secret000000000002", - "X_API_KEY=sk-secret000000000003", - "X_API_SECRET=sk-secret000000000004", - "X_ACCESS_TOKEN=sk-secret000000000005", - "X_ACCESS_TOKEN_SECRET=sk-secret000000000006", + "TAVILY_API_KEY=fixture-tavily-secret", + "XCRAWL_API_KEY=fixture-xcrawl-secret", + "BIRDREAD_API_KEY=fixture-birdread-secret", + "X_API_KEY=fixture-x-api-secret", + "X_API_SECRET=fixture-x-api-signing-secret", + "X_ACCESS_TOKEN=fixture-x-access-token", + "X_ACCESS_TOKEN_SECRET=fixture-x-access-token-secret", ] ) ) diff --git a/tests/test_config_and_secrets.py b/tests/test_config_and_secrets.py index fba334b..3fff103 100644 --- a/tests/test_config_and_secrets.py +++ b/tests/test_config_and_secrets.py @@ -71,7 +71,8 @@ def test_rejects_non_agent_id_before_write(self) -> None: def test_secret_report_exposes_names_only(self) -> None: with tempfile.TemporaryDirectory() as tmp: secret_file = Path(tmp) / "secrets.env" - secret_file.write_text("TAVILY_API_KEY=sk-secret000000000000\nUNUSED_API_KEY=fixture-unused\n") + secret_value = "fixture-tavily-secret-value" + secret_file.write_text(f"TAVILY_API_KEY={secret_value}\nUNUSED_API_KEY=fixture-unused\n") config = replace( default_config(secret_file), tools=(ToolSpec(id="agent-tavily", name="Tavily", command="tool", required_secrets=("TAVILY_API_KEY", "XCRAWL_API_KEY")),), @@ -81,7 +82,7 @@ def test_secret_report_exposes_names_only(self) -> None: self.assertIn("TAVILY_API_KEY", report.stored_names) self.assertIn("UNUSED_API_KEY", report.stored_names) self.assertNotIn("UNUSED_API_KEY", report.present_names) - self.assertNotIn("sk-secret", json.dumps(report.to_dict())) + self.assertNotIn(secret_value, json.dumps(report.to_dict())) self.assertIn("XCRAWL_API_KEY", report.missing) def test_non_secret_environment_round_trips_but_public_view_lists_names_only(self) -> None: