feat(platform): close AI expense value loop
Add tenant-safe value, telemetry, connector, commercial, and production-readiness foundations.
This commit is contained in:
@@ -8,17 +8,22 @@ from sqlalchemy.pool import StaticPool
|
||||
from app.core.agent_enums import AgentAssetDomain, AgentAssetStatus
|
||||
from app.db.base import Base
|
||||
from app.models.agent_asset import AgentAsset, AgentAssetTestRun, AgentAssetVersion
|
||||
from app.models.golden_case import GoldenCase
|
||||
from app.schemas.agent_asset import (
|
||||
AgentAssetRiskRuleDraftUpdate,
|
||||
AgentAssetRiskRuleGenerateRequest,
|
||||
AgentAssetRiskRuleRegenerateRequest,
|
||||
AgentAssetRiskRuleRevisionCreate,
|
||||
)
|
||||
from app.services.agent_asset_rule_library import AgentAssetRuleLibraryManager
|
||||
from app.services.agent_asset_release_guard import (
|
||||
AgentAssetReleaseGuardService,
|
||||
ReleaseEvaluationInput,
|
||||
)
|
||||
from app.services.agent_asset_risk_rule_regeneration import AgentAssetRiskRuleRegenerationService
|
||||
from app.services.agent_asset_risk_rule_revision import AgentAssetRiskRuleRevisionService
|
||||
from app.services.agent_asset_rule_library import AgentAssetRuleLibraryManager
|
||||
from app.services.agent_assets import AgentAssetService
|
||||
from app.services.risk_rule_generation import RiskRuleGenerationService
|
||||
from app.services.agent_asset_risk_rule_revision import AgentAssetRiskRuleRevisionService
|
||||
|
||||
|
||||
class NullRuntimeChatService:
|
||||
@@ -76,7 +81,9 @@ def test_update_published_rule_requires_revision(tmp_path) -> None:
|
||||
)
|
||||
|
||||
|
||||
def test_create_revision_draft_for_published_rule_does_not_overwrite_active_version(tmp_path) -> None:
|
||||
def test_create_revision_draft_for_published_rule_does_not_overwrite_active_version(
|
||||
tmp_path,
|
||||
) -> None:
|
||||
with build_session() as db:
|
||||
asset_id = _create_rule(db, tmp_path)
|
||||
asset = db.get(AgentAsset, asset_id)
|
||||
@@ -105,7 +112,10 @@ def test_create_revision_draft_for_published_rule_does_not_overwrite_active_vers
|
||||
assert updated.working_version == "v0.1.1"
|
||||
assert revision["version"] == "v0.1.1"
|
||||
assert revision["base_version"] == "v0.1.0"
|
||||
assert revision["generation_request"]["natural_language"] == "票据城市与申报目的地不一致时,要求补充说明。"
|
||||
assert (
|
||||
revision["generation_request"]["natural_language"]
|
||||
== "票据城市与申报目的地不一致时,要求补充说明。"
|
||||
)
|
||||
assert updated.config_json["last_operation"]["action"] == "create_revision"
|
||||
assert db.query(AgentAssetVersion).filter_by(asset_id=asset_id, version="v0.1.1").one()
|
||||
|
||||
@@ -251,21 +261,87 @@ def test_publish_regenerated_revision_replaces_online_document(tmp_path) -> None
|
||||
|
||||
service = AgentAssetService(db)
|
||||
service.rule_library_manager = manager
|
||||
revision_manifest = manager.read_rule_library_json(
|
||||
library="risk-rules",
|
||||
file_name=revision["rule_document"]["file_name"],
|
||||
)
|
||||
for case in service._build_default_sample_cases(revision_manifest):
|
||||
db.add(
|
||||
GoldenCase(
|
||||
case_key=f"{asset.code}:{case.case_id}",
|
||||
rule_code=asset.code,
|
||||
name=case.name,
|
||||
values_json=case.values,
|
||||
expected_hit=case.expected_hit,
|
||||
expected_severity=case.expected_severity,
|
||||
status="active",
|
||||
source="pytest",
|
||||
)
|
||||
)
|
||||
db.commit()
|
||||
published = service.publish_risk_rule(asset_id, actor="manager")
|
||||
|
||||
assert published.status == AgentAssetStatus.ACTIVE.value
|
||||
assert published.current_version == "v0.1.0"
|
||||
assert published.published_version == "v0.1.0"
|
||||
assert published.config_json["release_guard"]["stage"] == "shadow"
|
||||
release_guard = AgentAssetReleaseGuardService(
|
||||
db,
|
||||
rule_library_manager=manager,
|
||||
)
|
||||
release_guard.record_evaluation(
|
||||
asset_id,
|
||||
ReleaseEvaluationInput(
|
||||
total=20,
|
||||
failure_count=0,
|
||||
precision=1.0,
|
||||
details={
|
||||
"metric_source": "release_runtime_telemetry",
|
||||
"negative_ground_truth_status": "available",
|
||||
"recall_lower_bound": 1.0,
|
||||
},
|
||||
),
|
||||
actor="monitor",
|
||||
)
|
||||
release_guard.promote(asset_id, actor="manager")
|
||||
release_guard.record_evaluation(
|
||||
asset_id,
|
||||
ReleaseEvaluationInput(
|
||||
total=100,
|
||||
failure_count=0,
|
||||
precision=1.0,
|
||||
details={
|
||||
"metric_source": "release_runtime_telemetry",
|
||||
"negative_ground_truth_status": "available",
|
||||
"recall_lower_bound": 1.0,
|
||||
},
|
||||
),
|
||||
actor="monitor",
|
||||
)
|
||||
release_guard.promote(asset_id, actor="manager")
|
||||
published = db.get(AgentAsset, asset_id)
|
||||
assert published is not None
|
||||
assert published.current_version == "v0.1.1"
|
||||
assert published.published_version == "v0.1.1"
|
||||
assert "revision_draft" not in published.config_json
|
||||
assert published.config_json["rule_document"] == revision["rule_document"]
|
||||
assert published.config_json["revision_history"][0]["previous_rule_document"] == old_document
|
||||
assert published.config_json["last_operation"]["action"] == "publish_revision"
|
||||
assert (
|
||||
published.config_json["revision_history"][0]["previous_rule_document"] == old_document
|
||||
)
|
||||
assert published.config_json["last_operation"]["action"] == "activate_staged_release"
|
||||
manifest = manager.read_rule_library_json(
|
||||
library="risk-rules",
|
||||
file_name=published.config_json["rule_document"]["file_name"],
|
||||
)
|
||||
assert manifest["enabled"] is True
|
||||
assert manifest["enabled"] is False
|
||||
assert manifest["rule_code"] == published.code
|
||||
golden_run = service.repository.get_latest_test_run(
|
||||
asset_id,
|
||||
version="v0.1.1",
|
||||
test_type="golden",
|
||||
)
|
||||
assert golden_run is not None
|
||||
assert golden_run.passed is True
|
||||
|
||||
|
||||
def _create_rule(
|
||||
|
||||
Reference in New Issue
Block a user