diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ccc7519..efbb1e0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,15 +6,35 @@ on: - 'v*' permissions: - contents: read + contents: write jobs: release-gate: runs-on: macos-latest steps: - uses: actions/checkout@v7 + with: + fetch-depth: 0 - uses: actions/setup-python@v7 with: python-version: '3.11' - run: bash scripts/bootstrap_runtime.sh - run: ./scripts/trove-python scripts/check.py release + - name: Build and verify distribution + shell: bash + run: | + set -euo pipefail + test "$GITHUB_REF_NAME" = "v1.0.0" + ./scripts/trove-python scripts/build_distribution.py --out dist + ./scripts/trove-python scripts/verify_distribution.py \ + --manifest dist/distribution-manifest.json + - name: Create GitHub release + env: + GH_TOKEN: ${{ github.token }} + shell: bash + run: | + set -euo pipefail + gh release create "$GITHUB_REF_NAME" dist/* \ + --title "TROVE 1.0.0" \ + --notes-file CHANGELOG.md \ + --verify-tag diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..8b261a0 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,20 @@ +# Changelog + +All notable changes to TROVE are documented here. + +## 1.0.0 - 2026-08-11 + +### Added + +- Local-first `trove/1` runtime with CLI, MCP, and owner-only daemon surfaces. +- Bounded recall and search with citations, coverage metadata, cursors, and typed errors. +- Optional, independently packaged WeChat source Provider. +- Human-controlled operation approval and an optional Reply Runtime that is disabled by default. +- Privacy gates, synthetic fixtures, full-history secret scanning, and reproducible distribution manifests. +- English and Simplified Chinese documentation for installation, architecture, operations, and security. + +### Distribution + +- `trove-runtime` 1.0.0 wheel. +- `trove-provider-wechat` 1.0.0 wheel. +- A distribution manifest binding source commit, protocol, package identities, hashes, and privacy flags. diff --git a/README.md b/README.md index 5ff8cac..6fdd3f1 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@
+
@@ -181,6 +182,7 @@ The scanners are guardrails, not a substitute for human review. See
- [Operations and recovery](docs/operations.md)
- [Testing](docs/testing.md)
- [Release model](docs/release.md)
+- [Changelog](CHANGELOG.md)
- [Roadmap](docs/roadmap.md)
## Project activity
diff --git a/README.zh-CN.md b/README.zh-CN.md
index 15122ea..ca11520 100644
--- a/README.zh-CN.md
+++ b/README.zh-CN.md
@@ -15,6 +15,7 @@
+
@@ -145,6 +146,7 @@ gitleaks git --redact
- [运维与恢复](docs/operations.md)
- [测试](docs/testing.md)
- [发行模型](docs/release.md)
+- [更新记录](CHANGELOG.md)
- [路线图](docs/roadmap.md)
## 项目数据
diff --git a/packages/trove_core/tests/test_embedding_provider_contract.py b/packages/trove_core/tests/test_embedding_provider_contract.py
index cd53981..031fc88 100644
--- a/packages/trove_core/tests/test_embedding_provider_contract.py
+++ b/packages/trove_core/tests/test_embedding_provider_contract.py
@@ -63,12 +63,13 @@ def test_persisted_cloud_policy_never_silently_falls_back_local(self):
configured_embedding_provider(vault_root=vault)
def test_agent_switch_environment_adds_user_local_bin_for_launch_agents(self):
+ fixture_home = '/tmp/trove-fixture-home'
env = agent_switch_subprocess_environment({
- 'HOME': '/home/example',
+ 'HOME': fixture_home,
'PATH': '/usr/bin:/bin',
'DASHSCOPE_API_KEY': 'must-not-propagate',
})
- self.assertEqual(env['PATH'].split(os.pathsep)[0], '/home/example/.local/bin')
+ self.assertEqual(env['PATH'].split(os.pathsep)[0], f'{fixture_home}/.local/bin')
self.assertEqual(env['PATH'].split(os.pathsep)[1], '/opt/homebrew/bin')
self.assertNotIn('DASHSCOPE_API_KEY', env)
diff --git a/scripts/benchmark_agent_runtime.py b/scripts/benchmark_agent_runtime.py
index 6ca666f..bcb3a1d 100644
--- a/scripts/benchmark_agent_runtime.py
+++ b/scripts/benchmark_agent_runtime.py
@@ -501,7 +501,7 @@ def main(argv: list[str] | None = None) -> int:
parser.add_argument('--warmups', type=int, default=2)
parser.add_argument('--seed', type=int, default=20260621)
parser.add_argument('--out', default='docs/perf/agent-runtime-budgets.json')
- parser.add_argument('--baseline', help='Optional same-host baseline artifact for the 10% p95 regression gate.')
+ parser.add_argument('--baseline', help='Optional same-host baseline artifact for the 10%% p95 regression gate.')
args = parser.parse_args(argv)
artifact = run_fixture_baseline(rounds=args.rounds, warmups=args.warmups, seed=args.seed)
output = {
diff --git a/tests/test_agent_runtime_benchmark_contract.py b/tests/test_agent_runtime_benchmark_contract.py
index 3bdec9c..a9ed374 100644
--- a/tests/test_agent_runtime_benchmark_contract.py
+++ b/tests/test_agent_runtime_benchmark_contract.py
@@ -1,6 +1,8 @@
from __future__ import annotations
import unittest
+import contextlib
+import io
import json
from pathlib import Path
@@ -8,6 +10,7 @@
REQUIRED_MEASUREMENTS,
evaluate_absolute_budgets,
evaluate_relative_regressions,
+ main,
validate_benchmark_artifact,
)
from scripts.measure_agent_surface import estimate_json_tokens
@@ -16,6 +19,14 @@
class AgentRuntimeBenchmarkContractTests(unittest.TestCase):
+ def test_cli_help_renders_on_supported_python_versions(self):
+ output = io.StringIO()
+ with contextlib.redirect_stdout(output), self.assertRaises(SystemExit) as raised:
+ main(['--help'])
+ self.assertEqual(raised.exception.code, 0)
+ self.assertIn('10% p95', output.getvalue())
+ self.assertIn('regression gate', output.getvalue())
+
def _artifact(self) -> dict:
measurements = {
name: {