Merge remote-tracking branch 'gitea-ssh/main' into codex/github-redacted-evidence-validator-20260627

This commit is contained in:
Your Name
2026-06-28 19:01:42 +08:00
20 changed files with 1040 additions and 1056 deletions

View File

@@ -10,12 +10,13 @@ KM, and Telegram receipts are present.
from __future__ import annotations
from collections.abc import Iterable, Mapping
from datetime import datetime, timezone
from datetime import UTC, datetime
from typing import Any
from sqlalchemy import text
from src.core.config import settings
from src.core.logging import get_logger
from sqlalchemy import text
from src.db.base import get_db_context
from src.services.report_generation_service import (
DAILY_REPORT_HOUR_TAIPEI,
@@ -54,8 +55,8 @@ def _utc_iso(value: Any) -> str | None:
return None
if isinstance(value, datetime):
if value.tzinfo is None:
value = value.replace(tzinfo=timezone.utc)
return value.astimezone(timezone.utc).isoformat()
value = value.replace(tzinfo=UTC)
return value.astimezone(UTC).isoformat()
return str(value)
@@ -229,6 +230,188 @@ def _latest_flow_closure(
}
def classify_deploy_control_plane_observation(
*,
run_status: str,
is_latest_deploy_intent: bool,
active_task_container_count: int,
production_marker_hit: bool,
latest_flow_closed: bool,
runner_capacity_ok: bool,
runner_forbidden_label_count: int,
) -> dict[str, Any]:
"""Classify CD/run noise into an internal PlayBook decision."""
normalized_status = str(run_status or "unknown").strip().lower()
has_active_task = active_task_container_count > 0
runner_lane_safe = runner_capacity_ok and runner_forbidden_label_count == 0
production_truth_ok = production_marker_hit and latest_flow_closed
if not is_latest_deploy_intent:
classification = "superseded_run_skip"
action = "skip_cd_work_and_attach_to_superseded_intent"
elif production_truth_ok and normalized_status == "success":
classification = "deploy_succeeded_marker_hit"
action = "close_deploy_intent_and_write_receipts"
elif normalized_status == "running" and has_active_task and runner_lane_safe:
classification = "running_with_controlled_task"
action = "continue_observing_without_restarting_runner"
elif normalized_status == "running" and not has_active_task and production_truth_ok:
classification = "running_no_container_stale_ui"
action = "treat_gitea_spinner_as_stale_and_keep_production_truth"
elif normalized_status == "failure" and production_truth_ok:
classification = "failed_run_superseded_by_marker_hit"
action = "record_non_blocking_failure_and_keep_current_marker"
elif normalized_status == "failure":
classification = "real_failure_requires_playbook_repair"
action = "open_cd_repair_playbook_with_target_selector_and_verifier"
elif not runner_lane_safe:
classification = "runner_lane_guardrail_violation"
action = "fail_closed_runner_lane_and_open_repair_playbook"
else:
classification = "waiting_for_controlled_observation"
action = "wait_for_mcp_observation_or_deploy_intent_update"
return {
"schema_version": "ai_agent_deploy_control_plane_decision_v1",
"classification": classification,
"action": action,
"inputs": {
"run_status": normalized_status,
"is_latest_deploy_intent": is_latest_deploy_intent,
"active_task_container_count": max(0, active_task_container_count),
"production_marker_hit": production_marker_hit,
"latest_flow_closed": latest_flow_closed,
"runner_capacity_ok": runner_capacity_ok,
"runner_forbidden_label_count": max(0, runner_forbidden_label_count),
},
"internal_writeback": {
"mcp_event_type": "deploy_run_observation",
"rag_context_required": True,
"km_writeback_required": True,
"playbook_route_required": True,
"log_projection_required": True,
"telegram_receipt_required": classification in {
"deploy_succeeded_marker_hit",
"real_failure_requires_playbook_repair",
"runner_lane_guardrail_violation",
},
},
"safety_boundary": {
"reads_raw_sessions": False,
"reads_secret_values": False,
"opens_legacy_runner": False,
"uses_force_push": False,
"writes_runtime_state": classification in {
"deploy_succeeded_marker_hit",
"real_failure_requires_playbook_repair",
"runner_lane_guardrail_violation",
},
},
}
def _control_plane_integration() -> dict[str, Any]:
classifier_examples = [
classify_deploy_control_plane_observation(
run_status="success",
is_latest_deploy_intent=True,
active_task_container_count=0,
production_marker_hit=True,
latest_flow_closed=True,
runner_capacity_ok=True,
runner_forbidden_label_count=0,
),
classify_deploy_control_plane_observation(
run_status="running",
is_latest_deploy_intent=True,
active_task_container_count=0,
production_marker_hit=True,
latest_flow_closed=True,
runner_capacity_ok=True,
runner_forbidden_label_count=0,
),
classify_deploy_control_plane_observation(
run_status="failure",
is_latest_deploy_intent=True,
active_task_container_count=0,
production_marker_hit=False,
latest_flow_closed=False,
runner_capacity_ok=True,
runner_forbidden_label_count=0,
),
]
return {
"schema_version": "ai_agent_autonomous_runtime_internal_loop_v1",
"status": "mcp_rag_km_playbook_log_control_loop_declared",
"purpose": (
"把 Gitea run、runner lane、production marker、browser smoke 與 executor receipt "
"先收斂成內部事件,再由 PlayBook decision 推進或跳過。"
),
"mcp_sensors": [
{
"sensor_id": "gitea_actions_run_observer",
"normalized_event": "RunObservation",
"raw_secret_access_allowed": False,
},
{
"sensor_id": "controlled_runner_lane_observer",
"normalized_event": "RunnerLaneState",
"raw_runner_token_access_allowed": False,
},
{
"sensor_id": "production_marker_observer",
"normalized_event": "ProductionTruthSnapshot",
"raw_session_access_allowed": False,
},
{
"sensor_id": "browser_smoke_observer",
"normalized_event": "FrontendTruthSnapshot",
"raw_conversation_access_allowed": False,
},
],
"rag_context_queries": [
"runner_pressure_buildkit_stockplatform_collision",
"controlled_cd_lane_capacity_label_guardrails",
"autonomous_runtime_marker_receipt_contract",
],
"playbook_decision_classes": [
"deploy_succeeded_marker_hit",
"running_with_controlled_task",
"running_no_container_stale_ui",
"superseded_run_skip",
"failed_run_superseded_by_marker_hit",
"real_failure_requires_playbook_repair",
"runner_lane_guardrail_violation",
],
"km_writeback_contract": {
"knowledge_entry_path_type": "deploy_control_plane_decision:<deploy_intent_id>",
"required_refs": [
"deploy_intent_id",
"target_sha",
"gitea_run_id",
"production_marker",
"latest_flow_closure",
"runner_lane_state",
],
"stores_raw_logs": False,
"stores_secret_values": False,
},
"log_projection_contract": {
"timeline_event_type": "ai_agent_deploy_control_plane_decision",
"logbook_projection": "summary_only_after_verifier",
"raw_html_or_long_log_allowed": False,
},
"classifier_examples": classifier_examples,
"rollups": {
"mcp_sensor_count": 4,
"rag_context_query_count": 3,
"playbook_decision_class_count": 7,
"classifier_example_count": len(classifier_examples),
},
}
def build_runtime_receipt_readback_from_rows(
*,
project_id: str = _DEFAULT_PROJECT_ID,
@@ -483,9 +666,10 @@ def build_ai_agent_autonomous_runtime_control() -> dict[str, Any]:
"new_behavior": "用 Telegram Gateway 實送報告與 actionable receipt不直接暴露 Bot API",
},
]
control_plane_integration = _control_plane_integration()
payload = {
"schema_version": _SCHEMA_VERSION,
"generated_at": datetime.now(timezone.utc).isoformat(),
"generated_at": datetime.now(UTC).isoformat(),
"program_status": {
"current_task_id": "P2-416-D1N",
"status": "current_directive_control_plane_active",
@@ -565,6 +749,7 @@ def build_ai_agent_autonomous_runtime_control() -> dict[str, Any]:
"telegram_receipt_or_alert",
],
},
"control_plane_integration": control_plane_integration,
"legacy_policy_overrides": legacy_overrides,
"hard_blockers": hard_blockers,
"visibility_contract": {
@@ -589,6 +774,10 @@ def build_ai_agent_autonomous_runtime_control() -> dict[str, Any]:
1 for item in executor_receipts if item["writes_runtime_state"]
),
"legacy_policy_overridden_count": len(legacy_overrides),
"mcp_sensor_count": control_plane_integration["rollups"]["mcp_sensor_count"],
"rag_context_query_count": control_plane_integration["rollups"]["rag_context_query_count"],
"playbook_decision_class_count": control_plane_integration["rollups"]["playbook_decision_class_count"],
"deploy_control_classifier_example_count": control_plane_integration["rollups"]["classifier_example_count"],
},
}
_attach_runtime_receipt_readback(

View File

@@ -1,6 +1,7 @@
from src.services.ai_agent_autonomous_runtime_control import (
build_ai_agent_autonomous_runtime_control,
build_runtime_receipt_readback_from_rows,
classify_deploy_control_plane_observation,
)
@@ -58,6 +59,57 @@ def test_ai_agent_autonomous_runtime_control_exposes_reports_and_executor_receip
assert data["runtime_receipt_readback"]["db_read_status"] == "not_queried"
def test_ai_agent_autonomous_runtime_control_exposes_internal_control_loop():
data = build_ai_agent_autonomous_runtime_control()
integration = data["control_plane_integration"]
assert integration["schema_version"] == "ai_agent_autonomous_runtime_internal_loop_v1"
assert integration["status"] == "mcp_rag_km_playbook_log_control_loop_declared"
assert {sensor["normalized_event"] for sensor in integration["mcp_sensors"]} == {
"RunObservation",
"RunnerLaneState",
"ProductionTruthSnapshot",
"FrontendTruthSnapshot",
}
assert "controlled_cd_lane_capacity_label_guardrails" in integration["rag_context_queries"]
assert "running_no_container_stale_ui" in integration["playbook_decision_classes"]
assert integration["km_writeback_contract"]["stores_raw_logs"] is False
assert integration["km_writeback_contract"]["stores_secret_values"] is False
assert integration["log_projection_contract"]["raw_html_or_long_log_allowed"] is False
assert data["rollups"]["mcp_sensor_count"] == 4
assert data["rollups"]["playbook_decision_class_count"] == 7
def test_deploy_control_plane_classifier_separates_stale_spinner_from_real_failure():
stale = classify_deploy_control_plane_observation(
run_status="running",
is_latest_deploy_intent=True,
active_task_container_count=0,
production_marker_hit=True,
latest_flow_closed=True,
runner_capacity_ok=True,
runner_forbidden_label_count=0,
)
assert stale["classification"] == "running_no_container_stale_ui"
assert stale["action"] == "treat_gitea_spinner_as_stale_and_keep_production_truth"
assert stale["safety_boundary"]["writes_runtime_state"] is False
assert stale["internal_writeback"]["km_writeback_required"] is True
failure = classify_deploy_control_plane_observation(
run_status="failure",
is_latest_deploy_intent=True,
active_task_container_count=0,
production_marker_hit=False,
latest_flow_closed=False,
runner_capacity_ok=True,
runner_forbidden_label_count=0,
)
assert failure["classification"] == "real_failure_requires_playbook_repair"
assert failure["action"] == "open_cd_repair_playbook_with_target_selector_and_verifier"
assert failure["safety_boundary"]["opens_legacy_runner"] is False
assert failure["internal_writeback"]["playbook_route_required"] is True
def test_ai_agent_autonomous_runtime_control_keeps_hard_blockers_and_redaction():
data = build_ai_agent_autonomous_runtime_control()

View File

@@ -6,7 +6,6 @@ from src.services.ai_agent_autonomous_runtime_control import (
build_ai_agent_autonomous_runtime_control,
)
_PUBLIC_FORBIDDEN_TERMS = [
"工作視窗",
"對話內容",
@@ -77,6 +76,11 @@ def test_get_ai_agent_autonomous_runtime_control_api(monkeypatch):
"ai_agent_autonomous_runtime_receipt_readback_v1"
)
assert data["runtime_receipt_readback"]["db_read_status"] == "not_queried"
assert data["control_plane_integration"]["status"] == (
"mcp_rag_km_playbook_log_control_loop_declared"
)
assert data["rollups"]["mcp_sensor_count"] == 4
assert data["rollups"]["deploy_control_classifier_example_count"] == 3
def test_get_ai_agent_autonomous_runtime_control_api_redacts_public_terms(monkeypatch):