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
10 changes: 10 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@ on:
branches: [main]

jobs:
public-release-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Run public release scan
run: python voscript-api/scripts/public_release_scan.py --root .

lint:
runs-on: ubuntu-latest
steps:
Expand Down
11 changes: 6 additions & 5 deletions .github/workflows/claude-code-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ on:

permissions:
contents: read
id-token: write
pull-requests: write
issues: write

Expand Down Expand Up @@ -80,12 +79,14 @@ jobs:
- Synchronized English/Chinese documentation

The PR branch is already checked out in the current working directory.
Post feedback only through the official Claude Code Action GitHub integration.
Use only the configured ANTHROPIC_API_KEY and ANTHROPIC_BASE_URL for Claude access.
Do not start browser login or any interactive authorization flow.
Post feedback only through this GitHub Actions run.
Do not use the GitHub CLI and do not use a user-owned GitHub token.
If the official Claude GitHub App integration is unavailable, fail instead of posting as the repository owner.
If there are no actionable findings, post the standard no-findings confirmation through the action integration.
If non-interactive API-key review is unavailable, fail instead of falling back.
If there are no actionable findings, post the standard no-findings confirmation through the action.
Avoid formatting-only comments.

claude_args: |
--model ${{ env.CLAUDE_MODEL }}
--max-turns 30
--max-turns 8
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions app/providers/kernel_bridge/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,31 @@
status_payload_contract,
voiceprint_score,
)
from .release_gates import (
REQUIRED_CI_GATES,
REQUIRED_HARD_FAIL_MODES,
RUST_KERNEL_MODE_ROLLBACK,
RustKernelReleaseGate,
release_gate_matrix,
validate_release_gate_matrix,
)

__all__ = [
"REQUIRED_CI_GATES",
"REQUIRED_HARD_FAIL_MODES",
"RUST_KERNEL_MODE_OFF",
"RUST_KERNEL_MODE_REQUIRED",
"RUST_KERNEL_MODE_ROLLBACK",
"RustKernelBridgeError",
"RustKernelReleaseGate",
"artifact_manifest_contract",
"core_smoke",
"postprocess_segments",
"release_gate_matrix",
"require_rust_core",
"rust_kernel_mode",
"rust_provider_paths_enabled",
"status_payload_contract",
"validate_release_gate_matrix",
"voiceprint_score",
]
183 changes: 183 additions & 0 deletions app/providers/kernel_bridge/release_gates.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
"""Internal release-gate matrix for selected Rust-backed provider paths."""

from __future__ import annotations

from dataclasses import dataclass
from typing import Final

RUST_KERNEL_MODE_ROLLBACK: Final = "RUST_KERNEL_MODE=off"

HARD_FAIL_IMPORT_FAILURE: Final = "import_failure"
HARD_FAIL_CALL_FAILURE: Final = "call_failure"
HARD_FAIL_INVALID_PAYLOAD: Final = "invalid_payload"
HARD_FAIL_INVALID_RESPONSE: Final = "invalid_response"
HARD_FAIL_PARITY_MISMATCH: Final = "parity_mismatch"

REQUIRED_HARD_FAIL_MODES: Final = frozenset(
{
HARD_FAIL_IMPORT_FAILURE,
HARD_FAIL_CALL_FAILURE,
HARD_FAIL_INVALID_PAYLOAD,
HARD_FAIL_INVALID_RESPONSE,
HARD_FAIL_PARITY_MISMATCH,
}
)

REQUIRED_CI_GATES: Final = frozenset(
{
"python_unit_security_tests",
"kernel_bridge_smoke_tests",
"rust_fmt",
"rust_clippy",
"rust_tests",
"rust_wheel_smoke",
"docker_packaging_smoke",
"public_release_scan",
}
)


@dataclass(frozen=True, slots=True)
class RustKernelReleaseGate:
"""Audit contract for one selected Rust-backed implementation path.

The runtime switch stays intentionally small: Python owns orchestration and
public API shape; Rust owns only selected pure kernels/helpers. This matrix
makes the selected paths and their rollback/fail-closed evidence explicit.
"""

name: str
bridge_function: str
python_owner: str
rust_owner: str
rollback: str
regression_matrix: tuple[str, ...]
hard_fail_modes: frozenset[str]
ci_gates: frozenset[str]
performance_baseline: str
public_api_change: bool = False


SELECTED_RUST_KERNEL_GATES: Final = (
RustKernelReleaseGate(
name="voiceprint_scoring",
bridge_function="voiceprint_score",
python_owner="voiceprints.scoring.score_voiceprint_candidates",
rust_owner="voscript_core::voiceprint::score_voiceprint_candidates",
rollback=RUST_KERNEL_MODE_ROLLBACK,
regression_matrix=(
"raw_cosine_adaptive_threshold",
"asnorm_active_with_margin_guard",
"small_cohort_raw_fallback",
"non_finite_embedding_rejection",
"db_required_mode_payload_export",
"db_off_mode_python_scoring",
),
hard_fail_modes=REQUIRED_HARD_FAIL_MODES,
ci_gates=REQUIRED_CI_GATES,
performance_baseline="internal_scoring_only_synthetic",
),
RustKernelReleaseGate(
name="postprocess_segments",
bridge_function="postprocess_segments",
python_owner="postprocess.segments.build_result_segments",
rust_owner="voscript_core::postprocess::build_result_segments",
rollback=RUST_KERNEL_MODE_ROLLBACK,
regression_matrix=(
"word_normalization",
"adjacent_text_segment_merge",
"word_payload_merge_block",
"duplicate_display_name_disambiguation",
"stable_speaker_label_preservation",
),
hard_fail_modes=REQUIRED_HARD_FAIL_MODES,
ci_gates=REQUIRED_CI_GATES,
performance_baseline="internal_postprocess_only_synthetic",
),
RustKernelReleaseGate(
name="artifact_manifest_contract",
bridge_function="artifact_manifest_contract",
python_owner="pipeline.contracts.artifacts.build_artifact_manifest",
rust_owner="voscript_core::contracts::artifact_manifest_contract",
rollback=RUST_KERNEL_MODE_ROLLBACK,
regression_matrix=(
"public_safe_manifest_build",
"path_and_url_rejection",
"legacy_unknown_entry_tolerance",
"stable_optional_experimental_categories",
),
hard_fail_modes=REQUIRED_HARD_FAIL_MODES,
ci_gates=REQUIRED_CI_GATES,
performance_baseline="internal_helper_only_synthetic",
),
RustKernelReleaseGate(
name="status_payload_contract",
bridge_function="status_payload_contract",
python_owner="pipeline.contracts.status.build_status_payload",
rust_owner="voscript_core::contracts::status_payload_contract",
rollback=RUST_KERNEL_MODE_ROLLBACK,
regression_matrix=(
"known_status_normalization",
"unknown_legacy_status_to_failed",
"basename_only_filename",
"legacy_status_payload_compatibility",
),
hard_fail_modes=REQUIRED_HARD_FAIL_MODES,
ci_gates=REQUIRED_CI_GATES,
performance_baseline="internal_helper_only_synthetic",
),
)


def release_gate_matrix() -> tuple[RustKernelReleaseGate, ...]:
"""Return the selected Rust-backed release gates as an immutable tuple."""

return SELECTED_RUST_KERNEL_GATES


def validate_release_gate_matrix(
gates: tuple[RustKernelReleaseGate, ...] = SELECTED_RUST_KERNEL_GATES,
) -> tuple[str, ...]:
"""Return policy gaps that would block a 0.8.x Rust-backed release."""

gaps: list[str] = []
names: set[str] = set()
bridge_functions: set[str] = set()
for gate in gates:
if gate.name in names:
gaps.append(f"{gate.name}: duplicate gate name")
names.add(gate.name)
if gate.bridge_function in bridge_functions:
gaps.append(f"{gate.name}: duplicate bridge function")
bridge_functions.add(gate.bridge_function)
if not gate.regression_matrix:
gaps.append(f"{gate.name}: missing regression matrix")
missing_hard_fail = REQUIRED_HARD_FAIL_MODES.difference(gate.hard_fail_modes)
if missing_hard_fail:
gaps.append(
f"{gate.name}: missing hard-fail modes {sorted(missing_hard_fail)}"
)
missing_ci = REQUIRED_CI_GATES.difference(gate.ci_gates)
if missing_ci:
gaps.append(f"{gate.name}: missing CI gates {sorted(missing_ci)}")
if gate.rollback != RUST_KERNEL_MODE_ROLLBACK:
gaps.append(f"{gate.name}: rollback must be {RUST_KERNEL_MODE_ROLLBACK}")
if gate.public_api_change:
gaps.append(f"{gate.name}: public API change is not allowed in 0.8.4")
Comment on lines +165 to +166
return tuple(gaps)


__all__ = [
"HARD_FAIL_CALL_FAILURE",
"HARD_FAIL_IMPORT_FAILURE",
"HARD_FAIL_INVALID_PAYLOAD",
"HARD_FAIL_INVALID_RESPONSE",
"HARD_FAIL_PARITY_MISMATCH",
"REQUIRED_CI_GATES",
"REQUIRED_HARD_FAIL_MODES",
"RUST_KERNEL_MODE_ROLLBACK",
"RustKernelReleaseGate",
"SELECTED_RUST_KERNEL_GATES",
"release_gate_matrix",
"validate_release_gate_matrix",
]
2 changes: 1 addition & 1 deletion crates/voscript_core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "voscript_core"
version = "0.8.3"
version = "0.8.4"
edition = "2021"
license = "Apache-2.0"
publish = false
Expand Down
2 changes: 1 addition & 1 deletion crates/voscript_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ fn voscript_core(module: &Bound<'_, PyModule>) -> PyResult<()> {
mod tests {
#[test]
fn package_version_is_set() {
assert_eq!(super::PACKAGE_VERSION, "0.8.3");
assert_eq!(super::PACKAGE_VERSION, "0.8.4");
}

#[test]
Expand Down
6 changes: 6 additions & 0 deletions doc/changelog.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@
- Extended contract tests for legacy / unknown artifact manifests, persisted
status payloads, optional schema versions, and Rust artifact helper bridge
validation.
- Added a 0.8.4 Rust-kernel release-gate matrix covering selected
voiceprint, post-process, artifact, and status helper paths with explicit
hard-fail, rollback, CI, and internal performance-baseline evidence.
- Added a repository-owned public release scan and CI gate so PR/release checks
fail before private paths, raw validation material, real IDs, or secret-like
values reach public release text.

## 0.7.6 — Health, alignment, and embedding runtime fixes (2026-05-07)

Expand Down
5 changes: 5 additions & 0 deletions doc/changelog.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@
消歧和 word normalization。
- 扩展 contract 测试,覆盖旧版 / 未知 artifact manifest、持久化 status
payload、可选 schema version,以及 Rust artifact helper bridge 校验。
- 新增 0.8.4 Rust-kernel release-gate matrix,覆盖已选择的声纹计分、结果
后处理、artifact 与 status helper 路径,并明确 hard-fail、rollback、CI
和内部性能基线证据。
- 新增主仓自带的 public release scan 与 CI gate,避免 private path、原始验证材料、
真实 ID 或疑似密钥值进入公开 PR / release 文案。

## 0.7.6 — 健康检查、alignment 与 embedding 运行时修复 (2026-05-07)

Expand Down
4 changes: 2 additions & 2 deletions tests/unit/test_kernel_bridge.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def _core_smoke(payload):
return {
"ok": True,
"echoed": payload,
"version": "0.8.3",
"version": "0.8.4",
"capabilities": {"core_smoke": True, "rust_extension": True},
}

Expand All @@ -39,7 +39,7 @@ def test_core_smoke_round_trips_safe_payload_through_imported_extension():

assert result["ok"] is True
assert result["echoed"] == payload
assert result["version"] == "0.8.3"
assert result["version"] == "0.8.4"
assert result["capabilities"]["core_smoke"] is True


Expand Down
Loading
Loading