176 lines
7.1 KiB
Python
176 lines
7.1 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
|
|
import pytest
|
|
|
|
from src.services.ai_agent_version_freshness_snapshot import (
|
|
load_latest_ai_agent_version_freshness_snapshot,
|
|
)
|
|
|
|
|
|
def test_load_latest_ai_agent_version_freshness_snapshot_reads_committed_snapshot():
|
|
data = load_latest_ai_agent_version_freshness_snapshot()
|
|
|
|
assert data["schema_version"] == "ai_agent_version_freshness_snapshot_v1"
|
|
assert data["program_status"]["overall_completion_percent"] == 42
|
|
assert data["program_status"]["current_task_id"] == "P2-402B"
|
|
assert data["program_status"]["next_task_id"] == "P2-402C"
|
|
assert data["program_status"]["read_only_mode"] is True
|
|
assert (
|
|
data["program_status"]["runtime_authority"]
|
|
== "repo_only_snapshot_no_external_lookup_or_update"
|
|
)
|
|
assert data["scan_boundaries"]["read_only_repo_snapshot_allowed"] is True
|
|
assert data["scan_boundaries"]["schedule_activation_allowed"] is False
|
|
assert data["scan_boundaries"]["external_registry_lookup_allowed"] is False
|
|
assert data["scan_boundaries"]["package_upgrade_allowed"] is False
|
|
assert data["scan_boundaries"]["lockfile_write_allowed"] is False
|
|
assert data["scan_boundaries"]["telegram_direct_send_allowed"] is False
|
|
assert data["approval_boundaries"]["daily_schedule_enabled"] is False
|
|
assert data["approval_boundaries"]["package_or_model_upgrade_allowed"] is False
|
|
assert data["rollups"]["source_count"] == len(data["freshness_sources"]) == 12
|
|
assert data["rollups"]["repo_only_source_count"] == 12
|
|
assert data["rollups"]["agent_count"] == 3
|
|
assert data["rollups"]["daily_step_count"] == 5
|
|
assert data["rollups"]["mutation_allowed_source_count"] == 0
|
|
assert data["rollups"]["schedule_enabled_count"] == 0
|
|
assert data["rollups"]["telegram_direct_send_count"] == 0
|
|
assert "javascript_workspace_manifests" in data["rollups"]["action_required_source_ids"]
|
|
assert "dockerfiles" in data["rollups"]["action_required_source_ids"]
|
|
|
|
|
|
def test_ai_agent_version_freshness_snapshot_rejects_schedule_activation(tmp_path):
|
|
snapshot = _snapshot()
|
|
snapshot["scan_boundaries"]["schedule_activation_allowed"] = True
|
|
(tmp_path / "ai_agent_version_freshness_snapshot_2026-06-11.json").write_text(
|
|
json.dumps(snapshot),
|
|
encoding="utf-8",
|
|
)
|
|
|
|
with pytest.raises(ValueError, match="scan boundaries"):
|
|
load_latest_ai_agent_version_freshness_snapshot(tmp_path)
|
|
|
|
|
|
def test_ai_agent_version_freshness_snapshot_rejects_rollup_mismatch(tmp_path):
|
|
snapshot = _snapshot()
|
|
snapshot["rollups"]["source_count"] = 99
|
|
(tmp_path / "ai_agent_version_freshness_snapshot_2026-06-11.json").write_text(
|
|
json.dumps(snapshot),
|
|
encoding="utf-8",
|
|
)
|
|
|
|
with pytest.raises(ValueError, match="rollup counts"):
|
|
load_latest_ai_agent_version_freshness_snapshot(tmp_path)
|
|
|
|
|
|
def test_ai_agent_version_freshness_snapshot_rejects_external_lookup_source(tmp_path):
|
|
snapshot = _snapshot()
|
|
snapshot["freshness_sources"][0]["external_lookup_allowed"] = True
|
|
(tmp_path / "ai_agent_version_freshness_snapshot_2026-06-11.json").write_text(
|
|
json.dumps(snapshot),
|
|
encoding="utf-8",
|
|
)
|
|
|
|
with pytest.raises(ValueError, match="blocked_external_lookup_source_ids|repo-only"):
|
|
load_latest_ai_agent_version_freshness_snapshot(tmp_path)
|
|
|
|
|
|
def _snapshot() -> dict:
|
|
return {
|
|
"schema_version": "ai_agent_version_freshness_snapshot_v1",
|
|
"generated_at": "2026-06-11T22:45:00+08:00",
|
|
"program_status": {
|
|
"overall_completion_percent": 42,
|
|
"current_priority": "P2",
|
|
"current_task_id": "P2-402B",
|
|
"next_task_id": "P2-402C",
|
|
"read_only_mode": True,
|
|
"runtime_authority": "repo_only_snapshot_no_external_lookup_or_update",
|
|
"status_note": "測試。",
|
|
},
|
|
"scan_boundaries": {
|
|
"read_only_repo_snapshot_allowed": True,
|
|
"schedule_activation_allowed": False,
|
|
"workflow_write_allowed": False,
|
|
"external_registry_lookup_allowed": False,
|
|
"external_cve_lookup_allowed": False,
|
|
"package_installation_allowed": False,
|
|
"package_upgrade_allowed": False,
|
|
"lockfile_write_allowed": False,
|
|
"docker_build_allowed": False,
|
|
"image_pull_allowed": False,
|
|
"host_probe_allowed": False,
|
|
"auto_pr_allowed": False,
|
|
"auto_merge_allowed": False,
|
|
"telegram_direct_send_allowed": False,
|
|
"paid_external_service_allowed": False,
|
|
"production_route_change_allowed": False,
|
|
},
|
|
"agent_roles": [
|
|
{
|
|
"agent_id": "hermes",
|
|
"role": "測試。",
|
|
"autonomy_level": "L1_report_only",
|
|
"outputs": ["snapshot"],
|
|
"approval_gate": "read_only",
|
|
}
|
|
],
|
|
"repo_scan_summary": {
|
|
"javascript_workspace_count": 1,
|
|
"javascript_direct_dependency_count": 2,
|
|
"python_manifest_count": 1,
|
|
"dockerfile_count": 1,
|
|
"runtime_surface_count": 1,
|
|
"committed_inventory_refs": ["docs/evaluations/example.json"],
|
|
"stale_committed_inventory_refs": ["docs/evaluations/example.json"],
|
|
},
|
|
"daily_snapshot_design": [
|
|
{
|
|
"step_id": "collect",
|
|
"sequence": 1,
|
|
"owner_agent": "hermes",
|
|
"allowed_now": True,
|
|
"planned_output": "snapshot",
|
|
"blocked_now": ["upgrade"],
|
|
}
|
|
],
|
|
"freshness_sources": [
|
|
{
|
|
"source_id": "javascript_workspace_manifests",
|
|
"domain": "javascript_packages",
|
|
"source_type": "repo_only",
|
|
"owner_agent": "hermes",
|
|
"status": "action_required",
|
|
"freshness_basis": "manifest",
|
|
"current_signal": "test",
|
|
"external_lookup_allowed": False,
|
|
"mutation_allowed": False,
|
|
"action_required": True,
|
|
"evidence_refs": ["package.json"],
|
|
"next_action": "review",
|
|
}
|
|
],
|
|
"approval_boundaries": {
|
|
"daily_schedule_enabled": False,
|
|
"external_source_lookup_allowed": False,
|
|
"package_or_model_upgrade_allowed": False,
|
|
"host_or_k3s_probe_allowed": False,
|
|
"telegram_digest_send_allowed": False,
|
|
"gitea_pr_creation_allowed": False,
|
|
"production_route_change_allowed": False,
|
|
},
|
|
"rollups": {
|
|
"source_count": 1,
|
|
"repo_only_source_count": 1,
|
|
"agent_count": 1,
|
|
"daily_step_count": 1,
|
|
"action_required_source_ids": ["javascript_workspace_manifests"],
|
|
"blocked_external_lookup_source_ids": ["javascript_workspace_manifests"],
|
|
"mutation_allowed_source_count": 0,
|
|
"schedule_enabled_count": 0,
|
|
"telegram_direct_send_count": 0,
|
|
"next_approval_task_ids": ["P2-402C"],
|
|
},
|
|
}
|