Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restore a clean checkout before building the release

The preceding check.py release ends by running benchmark_agent_runtime.py, whose default output rewrites the tracked docs/perf/agent-runtime-budgets.json with the current SHA and measurements. Thus, whenever the gate succeeds, this build records source_dirty=true; verify_distribution.py currently accepts either boolean, so the following step publishes a distribution that violates the source_dirty=false release invariant and is rejected by the closeout checks. Write the benchmark artifact to a temporary path or restore it, then assert the checkout is clean before building.

Useful? React with 👍 / 👎.

./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
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<p align="center">
<a href="https://github.com/JNHFlow21/trove/actions/workflows/ci.yml"><img src="https://github.com/JNHFlow21/trove/actions/workflows/ci.yml/badge.svg" alt="CI status"></a>
<a href="https://github.com/JNHFlow21/trove/actions/workflows/privacy-scan.yml"><img src="https://github.com/JNHFlow21/trove/actions/workflows/privacy-scan.yml/badge.svg" alt="Privacy scan status"></a>
<a href="https://github.com/JNHFlow21/trove/releases/latest"><img src="https://img.shields.io/github/v/release/JNHFlow21/trove?label=release" alt="Latest GitHub release"></a>
<a href="https://www.apple.com/macos/"><img src="https://img.shields.io/badge/macOS-only-111111?logo=apple" alt="macOS only"></a>
<a href="https://www.python.org/"><img src="https://img.shields.io/badge/Python-3.11%2B-3776AB?logo=python&logoColor=white" alt="Python 3.11 or newer"></a>
<a href="LICENSE"><img src="https://img.shields.io/badge/license-Apache--2.0-111111.svg" alt="Apache License 2.0"></a>
Expand Down Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<p align="center">
<a href="https://github.com/JNHFlow21/trove/actions/workflows/ci.yml"><img src="https://github.com/JNHFlow21/trove/actions/workflows/ci.yml/badge.svg" alt="CI 状态"></a>
<a href="https://github.com/JNHFlow21/trove/actions/workflows/privacy-scan.yml"><img src="https://github.com/JNHFlow21/trove/actions/workflows/privacy-scan.yml/badge.svg" alt="隐私扫描状态"></a>
<a href="https://github.com/JNHFlow21/trove/releases/latest"><img src="https://img.shields.io/github/v/release/JNHFlow21/trove?label=release" alt="最新 GitHub Release"></a>
<a href="https://www.apple.com/macos/"><img src="https://img.shields.io/badge/macOS-only-111111?logo=apple" alt="仅支持 macOS"></a>
<a href="https://www.python.org/"><img src="https://img.shields.io/badge/Python-3.11%2B-3776AB?logo=python&logoColor=white" alt="Python 3.11 或更高版本"></a>
<a href="LICENSE"><img src="https://img.shields.io/badge/license-Apache--2.0-111111.svg" alt="Apache License 2.0"></a>
Expand Down Expand Up @@ -145,6 +146,7 @@ gitleaks git --redact
- [运维与恢复](docs/operations.md)
- [测试](docs/testing.md)
- [发行模型](docs/release.md)
- [更新记录](CHANGELOG.md)
- [路线图](docs/roadmap.md)

## 项目数据
Expand Down
5 changes: 3 additions & 2 deletions packages/trove_core/tests/test_embedding_provider_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
2 changes: 1 addition & 1 deletion scripts/benchmark_agent_runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down
11 changes: 11 additions & 0 deletions tests/test_agent_runtime_benchmark_contract.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
from __future__ import annotations

import unittest
import contextlib
import io
import json
from pathlib import Path

from scripts.benchmark_agent_runtime import (
REQUIRED_MEASUREMENTS,
evaluate_absolute_budgets,
evaluate_relative_regressions,
main,
validate_benchmark_artifact,
)
from scripts.measure_agent_surface import estimate_json_tokens
Expand All @@ -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: {
Expand Down