feat(telegram): verify alert context receipts
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Failing after 1m47s
CD Pipeline / build-and-deploy (push) Has been skipped
CD Pipeline / post-deploy-checks (push) Has been skipped

This commit is contained in:
Your Name
2026-07-02 20:59:59 +08:00
parent ef69616b6b
commit d99cb7b2a5
9 changed files with 901 additions and 16 deletions

View File

@@ -469,6 +469,9 @@ from src.services.stockplatform_public_api_runtime_readback import (
from src.services.telegram_alert_ai_automation_matrix import (
load_latest_telegram_alert_ai_automation_matrix,
)
from src.services.telegram_alert_learning_context_post_apply_verifier import (
load_latest_telegram_alert_learning_context_post_apply_verifier,
)
router = APIRouter(prefix="/agents", tags=["Agent Teams"])
logger = get_logger("awoooi.agents")
@@ -1144,11 +1147,15 @@ async def get_awoooi_priority_work_order_readback() -> dict[str, Any]:
consumer_readback = (
await load_latest_ai_agent_log_controlled_writeback_consumer_readback()
)
telegram_alert_context_verifier = (
await load_latest_telegram_alert_learning_context_post_apply_verifier()
)
apply_ai_automation_live_closure_readbacks(
payload,
executor_readback=log_executor,
verifier_readback=post_write_verifier,
consumer_readback=consumer_readback,
telegram_alert_context_verifier_readback=telegram_alert_context_verifier,
)
return redact_public_lan_topology(payload)
except FileNotFoundError as exc:
@@ -2464,6 +2471,34 @@ async def get_agent_log_controlled_writeback_consumer_readback() -> dict[str, An
) from exc
@router.get(
"/telegram-alert-learning-context-post-apply-verifier",
response_model=dict[str, Any],
summary="取得 Telegram alert learning context post-apply verifier",
description=(
"讀取 AI Loop consumer context 中的 Telegram alert learning receipts"
"驗證 target selector、source-of-truth diff、check-mode、rollback、"
"post verifier refs 與 metadata-only 邊界。此端點不寫 KM/RAG/PlayBook、"
"不呼叫 MCP tool、不發 Telegram、不觸發 workflow、不保存 raw payload、"
"不讀 secret、不呼叫 GitHub。"
),
)
async def get_telegram_alert_learning_context_post_apply_verifier() -> dict[str, Any]:
"""Read Telegram alert learning context post-apply verifier receipts."""
try:
payload = await load_latest_telegram_alert_learning_context_post_apply_verifier()
return redact_public_lan_topology(payload)
except (json.JSONDecodeError, ValueError) as exc:
logger.error(
"telegram_alert_learning_context_post_apply_verifier_invalid",
error=str(exc),
)
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Telegram alert learning context post-apply verifier 無效",
) from exc
@router.post(
"/agent-log-controlled-writeback-consumer-apply",
response_model=dict[str, Any],

View File

@@ -3899,6 +3899,7 @@ def apply_ai_automation_live_closure_readbacks(
executor_readback: dict[str, Any] | None = None,
verifier_readback: dict[str, Any] | None = None,
consumer_readback: dict[str, Any] | None = None,
telegram_alert_context_verifier_readback: dict[str, Any] | None = None,
) -> None:
"""Overlay live AI-loop executor/verifier/consumer readbacks onto receipts."""
@@ -4056,6 +4057,54 @@ def apply_ai_automation_live_closure_readbacks(
"ai_automation_consumer_runtime_target_write_performed"
]
telegram_verifier = _dict(telegram_alert_context_verifier_readback)
telegram_verifier_rollups = _dict(telegram_verifier.get("rollups"))
telegram_verifier_blockers = _strings(telegram_verifier.get("active_blockers"))
if telegram_verifier:
summary["ai_automation_telegram_alert_post_apply_verifier_status"] = str(
telegram_verifier.get("status") or ""
)
summary["ai_automation_telegram_alert_post_apply_verifier_ready"] = bool(
telegram_verifier_rollups.get(
"telegram_alert_learning_context_post_apply_verifier_ready"
)
is True
)
summary[
"ai_automation_telegram_alert_post_apply_verified_context_receipt_count"
] = _int(telegram_verifier_rollups.get("verified_context_receipt_count"))
summary[
"ai_automation_telegram_alert_post_apply_verified_target_count"
] = _int(telegram_verifier_rollups.get("verified_target_count"))
summary[
"ai_automation_telegram_alert_post_apply_verified_ai_agent_context_receipt_count"
] = _int(
telegram_verifier_rollups.get("verified_ai_agent_context_receipt_count")
)
summary[
"ai_automation_telegram_alert_post_apply_verifier_ref_count"
] = _int(telegram_verifier_rollups.get("post_apply_verifier_ref_count"))
summary["ai_automation_telegram_alert_post_apply_verifier_active_blockers"] = (
telegram_verifier_blockers
)
rollups["ai_automation_telegram_alert_post_apply_verifier_ready"] = summary[
"ai_automation_telegram_alert_post_apply_verifier_ready"
]
rollups[
"ai_automation_telegram_alert_post_apply_verified_context_receipt_count"
] = summary[
"ai_automation_telegram_alert_post_apply_verified_context_receipt_count"
]
rollups[
"ai_automation_telegram_alert_post_apply_verified_target_count"
] = summary["ai_automation_telegram_alert_post_apply_verified_target_count"]
rollups[
"ai_automation_telegram_alert_post_apply_verifier_active_blocker_count"
] = len(telegram_verifier_blockers)
state["ai_automation_telegram_alert_post_apply_verifier_ready"] = summary[
"ai_automation_telegram_alert_post_apply_verifier_ready"
]
apply_ai_automation_node_receipts(payload)
@@ -4136,6 +4185,20 @@ def _apply_ai_automation_node_receipts(payload: dict[str, Any]) -> None:
telegram_alert_ai_agent_context_receipt_count = _int(
summary.get("ai_automation_telegram_alert_ai_agent_context_receipt_count")
)
telegram_alert_post_apply_verifier_ready = bool(
summary.get("ai_automation_telegram_alert_post_apply_verifier_ready") is True
)
telegram_alert_post_apply_verified_context_receipt_count = _int(
summary.get(
"ai_automation_telegram_alert_post_apply_verified_context_receipt_count"
)
)
telegram_alert_post_apply_verified_target_count = _int(
summary.get("ai_automation_telegram_alert_post_apply_verified_target_count")
)
telegram_alert_post_apply_verifier_ref_count = _int(
summary.get("ai_automation_telegram_alert_post_apply_verifier_ref_count")
)
consumer_apply_route = str(summary.get("ai_automation_consumer_apply_route") or "")
normalizer_ready = bool(
queue_fields
@@ -4153,6 +4216,7 @@ def _apply_ai_automation_node_receipts(payload: dict[str, Any]) -> None:
post_verifier_ready = bool(
receipt_outputs
or verifier_dry_run_ready
or telegram_alert_post_apply_verifier_ready
or consumer_post_apply_verifier_ref_count > 0
)
learning_writeback_ready = bool(
@@ -4290,13 +4354,29 @@ def _apply_ai_automation_node_receipts(payload: dict[str, Any]) -> None:
*receipt_outputs[:4],
f"post_write_verifier_nodes:{verifier_passed_node_count}",
f"consumer_post_apply_verifier_refs:{consumer_post_apply_verifier_ref_count}",
(
"telegram_alert_post_apply_verified_context_receipts:"
f"{telegram_alert_post_apply_verified_context_receipt_count}"
),
(
"telegram_alert_post_apply_verified_targets:"
f"{telegram_alert_post_apply_verified_target_count}"
),
(
"telegram_alert_post_apply_verifier_refs:"
f"{telegram_alert_post_apply_verifier_ref_count}"
),
],
"verifier_result": "post_verifier_receipt_readback"
if receipt_outputs
else (
"verifier_result": (
"telegram_alert_learning_context_post_apply_verified"
if telegram_alert_post_apply_verifier_ready
else "post_verifier_receipt_readback"
if receipt_outputs
else (
"post_write_verifier_dry_run_ready"
if verifier_dry_run_ready
else "post_verifier_required"
)
),
"next_action": "read back route/API/UI/verifier output before closing",
},

View File

@@ -90,6 +90,9 @@ def load_latest_telegram_alert_ai_automation_matrix(
ai_loop_context_present = bool(
source_proof["telegram_alert_ai_loop_consumer_context_readback_present"]
)
post_apply_verifier_present = bool(
source_proof["telegram_alert_post_apply_verifier_readback_present"]
)
direct_gap_count = int(egress_summary["direct_bot_api_call_count"])
direct_gap_file_count = int(egress_summary["direct_bot_api_file_count"])
@@ -316,6 +319,46 @@ def load_latest_telegram_alert_ai_automation_matrix(
"/api/v1/agents/agent-log-controlled-writeback-consumer-readback",
],
},
{
"surface_id": "telegram_ai_loop_post_apply_verifier",
"priority_work_item_id": "CIR-P0-TG-001",
"surface_kind": "ai_loop_post_apply_verifier",
"status": (
"post_apply_verifier_readback_present"
if post_apply_verifier_present
else "post_apply_verifier_readback_missing"
),
"known_item_count": source_proof[
"telegram_alert_post_apply_verifier_readback_count"
],
"db_or_log_receipt": "ready_ai_loop_context_receipt_source",
"ai_route": (
"ready_verified_context_reuse"
if post_apply_verifier_present
else "missing_verified_context_reuse"
),
"controlled_queue": (
"ready_metadata_only_verifier"
if post_apply_verifier_present
else "missing_metadata_only_verifier"
),
"post_verifier": (
"ready_context_receipt_post_apply_verifier"
if post_apply_verifier_present
else "missing_context_receipt_post_apply_verifier"
),
"learning_writeback": (
"ready_verified_context_receipt_for_km_playbook_trust"
if post_apply_verifier_present
else "missing_verified_context_receipt"
),
"manual_default_gap_count": 0,
"direct_send_gap_count": 0,
"evidence_refs": [
"apps/api/src/services/telegram_alert_learning_context_post_apply_verifier.py",
"/api/v1/agents/telegram-alert-learning-context-post-apply-verifier",
],
},
]
next_priority_action = _next_priority_action(
@@ -325,6 +368,7 @@ def load_latest_telegram_alert_ai_automation_matrix(
learning_writeback_refs_present=learning_writeback_refs_present,
learning_registry_present=learning_registry_present,
ai_loop_context_present=ai_loop_context_present,
post_apply_verifier_present=post_apply_verifier_present,
)
next_controlled_actions = _ordered_controlled_actions(next_priority_action)
summary = _build_summary(
@@ -382,9 +426,17 @@ def load_latest_telegram_alert_ai_automation_matrix(
(
(
(
"Manual/default semantics are only acceptable for critical/break-glass or historical evidence; "
"Telegram alert registry is now consumable by AI Loop Agent context, "
"so the next P0 step is post-apply verifier receipt."
(
"Manual/default semantics are only acceptable for critical/break-glass or historical evidence; "
"Telegram alert AI Loop context has a post-apply verifier readback, "
"so the next P0 step is surfacing verified receipts in Runs / Work Items / Alerts."
)
if post_apply_verifier_present
else (
"Manual/default semantics are only acceptable for critical/break-glass or historical evidence; "
"Telegram alert registry is now consumable by AI Loop Agent context, "
"so the next P0 step is post-apply verifier receipt."
)
)
if ai_loop_context_present
else (
@@ -543,6 +595,10 @@ def _inspect_source_contract(repo_root: Path) -> dict[str, int | bool]:
"apps/api/src/services/ai_agent_log_controlled_writeback_consumer_readback.py",
"telegram_alert_ai_loop_consumer_context_readback_v1",
),
"telegram_alert_post_apply_verifier_readback_present": (
"apps/api/src/services/telegram_alert_learning_context_post_apply_verifier.py",
"telegram_alert_learning_context_post_apply_verifier_v1",
),
}
result: dict[str, int | bool] = {}
for key, (relative_path, marker) in source_checks.items():
@@ -561,6 +617,10 @@ def _inspect_source_contract(repo_root: Path) -> dict[str, int | bool]:
result["telegram_alert_ai_loop_consumer_context_readback_count"] = (
1 if present else 0
)
if key == "telegram_alert_post_apply_verifier_readback_present":
result["telegram_alert_post_apply_verifier_readback_count"] = (
1 if present else 0
)
required = [key for key, value in result.items() if key.endswith("_present") and value is not True]
if required:
@@ -588,6 +648,7 @@ def _next_priority_action(
learning_writeback_refs_present: bool,
learning_registry_present: bool,
ai_loop_context_present: bool,
post_apply_verifier_present: bool,
) -> dict[str, Any]:
if api_direct_gap_count > 0:
return {
@@ -649,14 +710,24 @@ def _next_priority_action(
"requires_runtime_send": False,
"post_verifier": "AI Loop Agent context readback references the CIR-P0-TG-001 Telegram alert learning registry.",
}
if not post_apply_verifier_present:
return {
"action_id": "verify_telegram_alert_learning_context_receipts_with_ai_loop_post_apply_verifier",
"scope": "AI Loop Agent Telegram alert consumer context -> post-apply verifier receipt",
"priority": "P0",
"why": "Telegram alert learning registry is readable by AI Loop Agent context; the next closure is verifier receipt and controlled apply reuse.",
"requires_secret": False,
"requires_runtime_send": False,
"post_verifier": "AI Loop post-apply verifier reads Telegram alert context receipts and reports reusable decision context.",
}
return {
"action_id": "verify_telegram_alert_learning_context_receipts_with_ai_loop_post_apply_verifier",
"scope": "AI Loop Agent Telegram alert consumer context -> post-apply verifier receipt",
"action_id": "surface_verified_telegram_alert_context_receipts_in_awooop_runs_work_items_alerts",
"scope": "Verified Telegram alert context receipts -> AwoooP Runs / Work Items / Alerts",
"priority": "P0",
"why": "Telegram alert learning registry is readable by AI Loop Agent context; the next closure is verifier receipt and controlled apply reuse.",
"why": "Post-apply verifier is source-controlled; the next closure is visible AI automation proof across operator surfaces.",
"requires_secret": False,
"requires_runtime_send": False,
"post_verifier": "AI Loop post-apply verifier reads Telegram alert context receipts and reports reusable decision context.",
"post_verifier": "Runs, Work Items, and Alerts surfaces show verified Telegram alert AI Loop receipts without manual-default terminal states.",
}
@@ -725,6 +796,9 @@ def _build_summary(
"telegram_alert_ai_loop_consumer_context_readback_count": source_proof[
"telegram_alert_ai_loop_consumer_context_readback_count"
],
"telegram_alert_post_apply_verifier_readback_count": source_proof[
"telegram_alert_post_apply_verifier_readback_count"
],
"next_priority_action_id": next_priority_action["action_id"],
"next_priority_work_item_id": "CIR-P0-TG-001",
}

View File

@@ -0,0 +1,350 @@
"""Telegram alert learning context post-apply verifier readback.
Verifies metadata-only Telegram alert learning context receipts emitted by the
AI Loop consumer readback. This module only reads public-safe receipt metadata;
it does not write KM/RAG/PlayBook, call MCP tools, send Telegram, or touch
runtime infrastructure.
"""
from __future__ import annotations
from collections.abc import Mapping
from typing import Any
from src.services.ai_agent_log_controlled_writeback_consumer_readback import (
load_latest_ai_agent_log_controlled_writeback_consumer_readback,
)
SCHEMA_VERSION = "telegram_alert_learning_context_post_apply_verifier_v1"
DEFAULT_PROJECT_ID = "awoooi"
_TARGETS = ("km", "rag", "playbook", "mcp", "verifier", "ai_agent")
_REQUIRED_TARGET_SELECTOR_FIELDS = (
"project_id",
"run_id",
"message_id",
"target",
"source_ref",
)
_REQUIRED_CHECKS = (
"ai_alert_card_delivery_receipt_present",
"learning_registry_binding_ready",
"metadata_only_raw_payload_absent",
"ai_agent_context_ref_present",
)
async def load_latest_telegram_alert_learning_context_post_apply_verifier(
*,
project_id: str = DEFAULT_PROJECT_ID,
) -> dict[str, Any]:
"""Return post-apply verifier results for Telegram alert context receipts."""
consumer_readback = (
await load_latest_ai_agent_log_controlled_writeback_consumer_readback(
project_id=project_id
)
)
return build_telegram_alert_learning_context_post_apply_verifier(
consumer_readback=consumer_readback,
project_id=project_id,
)
def build_telegram_alert_learning_context_post_apply_verifier(
*,
consumer_readback: Mapping[str, Any],
project_id: str = DEFAULT_PROJECT_ID,
) -> dict[str, Any]:
"""Build a deterministic verifier readback from consumer context receipts."""
consumer = _dict(consumer_readback)
telegram_context = _dict(consumer.get("telegram_alert_learning_context"))
context_receipts = [
_dict(receipt) for receipt in _list(telegram_context.get("context_receipts"))
]
verifier_results = [
_verify_context_receipt(receipt) for receipt in context_receipts
]
target_count = _safe_int(telegram_context.get("target_count")) or len(_TARGETS)
verified_targets = sorted(
{
str(item["target"])
for item in verifier_results
if item["verifier_status"] == "passed"
}
)
verified_ai_agent_count = sum(
1
for item in verifier_results
if item["target"] == "ai_agent" and item["verifier_status"] == "passed"
)
failed_results = [
item for item in verifier_results if item["verifier_status"] != "passed"
]
source_ready = (
telegram_context.get("status") == "ai_loop_agent_context_receipt_ready"
)
ready = bool(
source_ready
and context_receipts
and not failed_results
and len(verified_targets) == target_count
and verified_ai_agent_count > 0
)
active_blockers = _active_blockers(
source_ready=source_ready,
context_receipts=context_receipts,
failed_results=failed_results,
verified_targets=verified_targets,
target_count=target_count,
verified_ai_agent_count=verified_ai_agent_count,
)
return {
"schema_version": SCHEMA_VERSION,
"priority": "P0-TELEGRAM-AI-LOOP-POST-APPLY-VERIFIER",
"priority_work_item_id": "CIR-P0-TG-001",
"project_id": project_id,
"status": (
"telegram_alert_learning_context_post_apply_verified"
if ready
else "blocked_telegram_alert_learning_context_post_apply_verifier"
),
"source_readback": {
"source_endpoint": (
"/api/v1/agents/agent-log-controlled-writeback-consumer-readback"
),
"source_schema_version": consumer.get("schema_version"),
"telegram_context_schema_version": telegram_context.get("schema_version"),
"telegram_context_status": telegram_context.get("status"),
"consumer_context_route": telegram_context.get("consumer_context_route"),
"source_registry_status": telegram_context.get("source_registry_status"),
},
"controlled_verifier": {
"mode": "metadata_only_post_apply_verifier_readback",
"post_apply_verifier_executed": True,
"controlled_apply_allowed_for_low_medium_high": ready,
"owner_review_required_for_low_medium_high": False,
"critical_break_glass_required": True,
"target_selector_verified": ready,
"source_of_truth_diff_verified": ready,
"check_mode_verified": ready,
"rollback_verified": ready,
"raw_payload_absence_verified": ready,
},
"verifier_results": verifier_results,
"rollups": {
"telegram_alert_learning_context_post_apply_verifier_ready": ready,
"source_context_ready": source_ready,
"context_receipt_count": len(context_receipts),
"verified_context_receipt_count": sum(
1 for item in verifier_results if item["verifier_status"] == "passed"
),
"failed_context_receipt_count": len(failed_results),
"target_count": target_count,
"verified_target_count": len(verified_targets),
"verified_targets": verified_targets,
"verified_ai_agent_context_receipt_count": verified_ai_agent_count,
"target_selector_verified_count": sum(
1 for item in verifier_results if item["target_selector_verified"]
),
"source_of_truth_diff_verified_count": sum(
1
for item in verifier_results
if item["source_of_truth_diff_verified"]
),
"check_mode_verified_count": sum(
1 for item in verifier_results if item["check_mode_verified"]
),
"rollback_verified_count": sum(
1 for item in verifier_results if item["rollback_verified"]
),
"post_apply_verifier_ref_count": sum(
len(item["post_apply_verifier_refs"]) for item in verifier_results
),
"metadata_only_receipt_count": sum(
1 for item in verifier_results if item["metadata_only"] is True
),
"raw_payload_included_count": sum(
1 for item in verifier_results if item["raw_payload_included"] is True
),
"runtime_write_performed_count": 0,
"telegram_send_performed_count": 0,
"mcp_tool_call_performed_count": 0,
"secret_value_read_count": 0,
},
"active_blockers": active_blockers,
"next_action": (
"surface_verified_telegram_alert_context_receipts_in_awooop_runs_work_items_alerts"
if ready
else "fix_failed_telegram_alert_context_receipts_then_rerun_post_apply_verifier"
),
"operation_boundaries": {
"metadata_read_performed": True,
"post_apply_verifier_read_performed": True,
"runtime_target_write_performed": False,
"km_write_performed": False,
"rag_index_write_performed": False,
"playbook_trust_write_performed": False,
"mcp_tool_call_performed": False,
"agent_runtime_action_performed": False,
"telegram_send_performed": False,
"workflow_trigger_performed": False,
"raw_payload_included": False,
"secret_value_collection_allowed": False,
"github_api_used": False,
},
}
def _verify_context_receipt(receipt: dict[str, Any]) -> dict[str, Any]:
target = str(receipt.get("target") or "")
target_selector = _dict(receipt.get("target_selector"))
source_diff = _dict(receipt.get("source_of_truth_diff"))
check_mode = _dict(receipt.get("check_mode"))
rollback = _dict(receipt.get("rollback"))
post_apply_verifier = _dict(receipt.get("post_apply_verifier"))
verifier_refs = _strings(post_apply_verifier.get("verifier_refs"))
target_selector_missing = [
key for key in _REQUIRED_TARGET_SELECTOR_FIELDS if not target_selector.get(key)
]
checks = _strings(check_mode.get("checks"))
missing_checks = [check for check in _REQUIRED_CHECKS if check not in checks]
failed_checks: list[str] = []
if target not in _TARGETS:
failed_checks.append("target_in_allowed_set")
if receipt.get("status") != "ready_for_ai_loop_context":
failed_checks.append("receipt_ready_for_ai_loop_context")
if target_selector_missing:
failed_checks.append("target_selector_required_fields_present")
if not _source_diff_verified(source_diff, target):
failed_checks.append("source_of_truth_diff_verified")
if check_mode.get("enabled") is not True or missing_checks:
failed_checks.append("check_mode_required_checks_present")
if rollback.get("required") is not True or not rollback.get("rollback_ref"):
failed_checks.append("rollback_ref_present")
if post_apply_verifier.get("required") is not True or not verifier_refs:
failed_checks.append("post_apply_verifier_refs_present")
if receipt.get("metadata_only") is not True:
failed_checks.append("metadata_only_receipt")
if receipt.get("raw_payload_included") is not False:
failed_checks.append("raw_payload_absent")
if receipt.get("target_write_performed") is not False:
failed_checks.append("target_write_not_performed_by_verifier")
if not receipt.get("ai_agent_context_ref"):
failed_checks.append("ai_agent_context_ref_present")
passed_checks = [
"target_in_allowed_set",
"receipt_ready_for_ai_loop_context",
"target_selector_required_fields_present",
"source_of_truth_diff_verified",
"check_mode_required_checks_present",
"rollback_ref_present",
"post_apply_verifier_refs_present",
"metadata_only_receipt",
"raw_payload_absent",
"target_write_not_performed_by_verifier",
"ai_agent_context_ref_present",
]
passed_checks = [check for check in passed_checks if check not in failed_checks]
return {
"receipt_id": str(receipt.get("receipt_id") or ""),
"source_receipt_id": str(receipt.get("source_receipt_id") or ""),
"source_run_id": str(receipt.get("source_run_id") or ""),
"source_message_id": str(receipt.get("source_message_id") or ""),
"work_item_id": str(receipt.get("work_item_id") or "CIR-P0-TG-001"),
"target": target,
"consumer_surface": str(receipt.get("consumer_surface") or ""),
"verifier_status": "passed" if not failed_checks else "failed",
"passed_checks": passed_checks,
"failed_checks": failed_checks,
"target_selector_verified": not target_selector_missing,
"target_selector_missing_fields": target_selector_missing,
"source_of_truth_diff_verified": _source_diff_verified(source_diff, target),
"check_mode_verified": check_mode.get("enabled") is True and not missing_checks,
"check_mode_missing_checks": missing_checks,
"rollback_verified": (
rollback.get("required") is True and bool(rollback.get("rollback_ref"))
),
"post_apply_verifier_refs": verifier_refs,
"metadata_only": receipt.get("metadata_only") is True,
"raw_payload_included": receipt.get("raw_payload_included") is True,
"runtime_target_write_performed": False,
"telegram_send_performed": False,
"evidence_refs": _unique(
[
str(receipt.get("source_ref") or ""),
str(receipt.get("ai_agent_context_ref") or ""),
*verifier_refs,
]
),
}
def _active_blockers(
*,
source_ready: bool,
context_receipts: list[dict[str, Any]],
failed_results: list[dict[str, Any]],
verified_targets: list[str],
target_count: int,
verified_ai_agent_count: int,
) -> list[str]:
blockers: list[str] = []
if not source_ready:
blockers.append("telegram_alert_learning_context_source_not_ready")
if not context_receipts:
blockers.append("telegram_alert_learning_context_receipts_missing")
if len(verified_targets) < target_count:
blockers.append("telegram_alert_learning_context_verified_target_count_below_target")
if verified_ai_agent_count <= 0:
blockers.append("telegram_alert_learning_context_ai_agent_receipt_not_verified")
for item in failed_results:
receipt_id = item.get("receipt_id") or "unknown-receipt"
blockers.append(f"telegram_alert_context_receipt_verifier_failed:{receipt_id}")
return blockers
def _source_diff_verified(source_diff: dict[str, Any], target: str) -> bool:
return bool(
source_diff.get("current_state") == "telegram_alert_learning_registry_readable"
and source_diff.get("desired_state")
== "ai_loop_agent_context_receipt_available"
and source_diff.get("delta_kind") == f"telegram_alert_{target}_context_binding"
and source_diff.get("raw_payload_included") is False
)
def _dict(value: Any) -> dict[str, Any]:
return value if isinstance(value, dict) else {}
def _list(value: Any) -> list[Any]:
return value if isinstance(value, list) else []
def _strings(value: Any) -> list[str]:
return [str(item) for item in _list(value) if str(item)]
def _unique(values: list[str]) -> list[str]:
seen: set[str] = set()
result: list[str] = []
for value in values:
if value in seen:
continue
seen.add(value)
result.append(value)
return result
def _safe_int(value: Any) -> int:
try:
return int(value)
except (TypeError, ValueError):
return 0

View File

@@ -30,6 +30,9 @@ from src.services.awoooi_priority_work_order_readback import (
from src.services.harbor_registry_controlled_recovery_preflight import (
load_latest_harbor_registry_controlled_recovery_preflight,
)
from src.services.telegram_alert_learning_context_post_apply_verifier import (
build_telegram_alert_learning_context_post_apply_verifier,
)
from src.services.stockplatform_public_api_controlled_recovery_preflight import (
load_latest_stockplatform_public_api_controlled_recovery_preflight,
)
@@ -472,6 +475,7 @@ def test_ai_automation_live_closure_readbacks_close_node_receipts():
executor_readback=executor,
verifier_readback=verifier,
consumer_readback=_consumer_readback_ready(),
telegram_alert_context_verifier_readback=_telegram_alert_context_verifier_ready(),
)
receipts_by_id = {
@@ -490,7 +494,7 @@ def test_ai_automation_live_closure_readbacks_close_node_receipts():
"controlled_consumer_context_receipt_readback"
)
assert receipts_by_id["post_verifier"]["verifier_result"] == (
"post_write_verifier_dry_run_ready"
"telegram_alert_learning_context_post_apply_verified"
)
assert receipts_by_id["learning_writeback"]["verifier_result"] == (
"consumer_context_receipt_writeback_ready"
@@ -508,6 +512,12 @@ def test_ai_automation_live_closure_readbacks_close_node_receipts():
assert payload["summary"][
"ai_automation_consumer_target_context_receipt_write_count"
] == 6
assert payload["summary"][
"ai_automation_telegram_alert_post_apply_verifier_ready"
] is True
assert payload["summary"][
"ai_automation_telegram_alert_post_apply_verified_context_receipt_count"
] == 6
def test_awoooi_priority_work_order_readback_endpoint_returns_snapshot(
@@ -533,6 +543,11 @@ def test_awoooi_priority_work_order_readback_endpoint_returns_snapshot(
"load_latest_ai_agent_log_controlled_writeback_consumer_readback",
_consumer_readback_ready_async,
)
monkeypatch.setattr(
agents,
"load_latest_telegram_alert_learning_context_post_apply_verifier",
_telegram_alert_context_verifier_ready_async,
)
app = FastAPI()
app.include_router(router, prefix="/api/v1")
client = TestClient(app)
@@ -626,6 +641,9 @@ def test_awoooi_priority_work_order_readback_endpoint_returns_snapshot(
)
assert endpoint_receipts["execution_boundary"]["node_status"] == "ready"
assert endpoint_receipts["post_verifier"]["node_status"] == "ready"
assert endpoint_receipts["post_verifier"]["verifier_result"] == (
"telegram_alert_learning_context_post_apply_verified"
)
assert endpoint_receipts["learning_writeback"]["node_status"] == "ready"
assert endpoint_receipts["learning_writeback"]["km_writeback_ref"] == (
"context_receipt:km=1"
@@ -1648,6 +1666,84 @@ async def _consumer_readback_ready_async() -> dict:
return _consumer_readback_ready()
async def _telegram_alert_context_verifier_ready_async() -> dict:
return _telegram_alert_context_verifier_ready()
def _telegram_alert_context_verifier_ready() -> dict:
return build_telegram_alert_learning_context_post_apply_verifier(
consumer_readback=_consumer_readback_ready()
)
def _telegram_context_receipts() -> list[dict]:
targets = [
("km", "knowledge_memory_context"),
("rag", "rag_index_candidate_context"),
("playbook", "playbook_trust_candidate_context"),
("mcp", "mcp_audit_feedback_context"),
("verifier", "post_apply_verifier_feedback_context"),
("ai_agent", "autonomous_runtime_decision_context"),
]
return [
{
"receipt_id": f"telegram_alert_learning_context::msg-telegram-1::{target}",
"source_receipt_id": "msg-telegram-1",
"source_run_id": "run-telegram-1",
"source_message_id": "msg-telegram-1",
"work_item_id": "CIR-P0-TG-001",
"target": target,
"consumer_surface": surface,
"source_ref": f"{target}://awoooi/telegram-alert/msg-telegram-1",
"ai_agent_context_ref": (
"ai-agent://awoooi/telegram-alert-learning-context/"
"run-telegram-1/msg-telegram-1"
),
"status": "ready_for_ai_loop_context",
"metadata_only": True,
"target_write_performed": False,
"raw_payload_included": False,
"target_selector": {
"project_id": "awoooi",
"run_id": "run-telegram-1",
"message_id": "msg-telegram-1",
"target": target,
"source_ref": f"{target}://awoooi/telegram-alert/msg-telegram-1",
},
"source_of_truth_diff": {
"current_state": "telegram_alert_learning_registry_readable",
"desired_state": "ai_loop_agent_context_receipt_available",
"delta_kind": f"telegram_alert_{target}_context_binding",
"raw_payload_included": False,
},
"check_mode": {
"enabled": True,
"checks": [
"ai_alert_card_delivery_receipt_present",
"learning_registry_binding_ready",
"metadata_only_raw_payload_absent",
"ai_agent_context_ref_present",
],
},
"rollback": {
"required": True,
"rollback_ref": (
"rollback://telegram-alert-learning-context/"
f"msg-telegram-1/{target}"
),
},
"post_apply_verifier": {
"required": True,
"verifier_refs": [
"verifier://awoooi/telegram-alert-delivery-receipt/run-telegram-1",
f"{target}://awoooi/telegram-alert/msg-telegram-1",
],
},
}
for target, surface in targets
]
def _consumer_readback_ready() -> dict:
return {
"schema_version": "ai_agent_log_controlled_writeback_consumer_readback_v1",
@@ -1691,6 +1787,43 @@ def _consumer_readback_ready() -> dict:
"verifier_context_receipt_write_count": 1,
"ai_agent_context_receipt_write_count": 1,
"runtime_target_write_performed": True,
"telegram_alert_learning_context_readback_ready": True,
"telegram_alert_learning_context_receipt_count": 6,
"telegram_alert_learning_ai_agent_context_receipt_count": 1,
"telegram_alert_learning_ready_target_count": 6,
"telegram_alert_learning_target_count": 6,
},
"telegram_alert_learning_context": {
"schema_version": "telegram_alert_ai_loop_consumer_context_readback_v1",
"status": "ai_loop_agent_context_receipt_ready",
"priority_work_item_id": "CIR-P0-TG-001",
"project_id": "awoooi",
"source_endpoint": "/api/v1/platform/runs/ai-alert-cards",
"source_registry_status": "learning_registry_ready",
"consumer_context_route": "ai_loop_agent.telegram_alert_learning_context",
"target_count": 6,
"ready_target_count": 6,
"context_receipt_count": 6,
"ai_agent_context_receipt_count": 1,
"next_action": (
"verify_telegram_alert_learning_context_receipts_with_ai_loop_post_apply_verifier"
),
"context_receipts": _telegram_context_receipts(),
"active_blockers": [],
"operation_boundaries": {
"metadata_read_performed": True,
"db_or_log_receipt_read_performed": True,
"runtime_target_write_performed": False,
"km_write_performed": False,
"rag_index_write_performed": False,
"playbook_trust_write_performed": False,
"mcp_tool_call_performed": False,
"agent_runtime_action_performed": False,
"telegram_send_performed": False,
"raw_payload_included": False,
"secret_value_collection_allowed": False,
"github_api_used": False,
},
},
"active_blockers": [],
}

View File

@@ -32,7 +32,7 @@ def test_telegram_alert_ai_automation_matrix_loader_returns_gap_matrix():
}
summary = payload["summary"]
assert summary["telegram_alert_surface_count"] == 7
assert summary["telegram_alert_surface_count"] == 8
assert summary["known_direct_send_gap_count"] == 0
assert summary["known_direct_send_gap_file_count"] == 0
assert summary["workflow_direct_send_gap_count"] == 0
@@ -55,8 +55,9 @@ def test_telegram_alert_ai_automation_matrix_loader_returns_gap_matrix():
assert summary["ai_alert_card_learning_writeback_refs_count"] == 1
assert summary["ai_alert_card_learning_registry_readback_count"] == 1
assert summary["telegram_alert_ai_loop_consumer_context_readback_count"] == 1
assert summary["telegram_alert_post_apply_verifier_readback_count"] == 1
assert summary["next_priority_action_id"] == (
"verify_telegram_alert_learning_context_receipts_with_ai_loop_post_apply_verifier"
"surface_verified_telegram_alert_context_receipts_in_awooop_runs_work_items_alerts"
)
matrix = {item["surface_id"]: item for item in payload["matrix"]}
@@ -95,6 +96,12 @@ def test_telegram_alert_ai_automation_matrix_loader_returns_gap_matrix():
assert matrix["telegram_ai_loop_agent_consumer_context"]["ai_route"] == (
"ready_ai_loop_agent_context_reuse"
)
assert matrix["telegram_ai_loop_post_apply_verifier"]["status"] == (
"post_apply_verifier_readback_present"
)
assert matrix["telegram_ai_loop_post_apply_verifier"]["post_verifier"] == (
"ready_context_receipt_post_apply_verifier"
)
assert payload["direct_send_gap_refs"] == []
assert not any(
@@ -142,6 +149,10 @@ def test_telegram_matrix_source_contract_supports_container_layout(tmp_path):
"telegram_alert_ai_loop_consumer_context_readback_v1\n",
encoding="utf-8",
)
(tmp_path / "src/services/telegram_alert_learning_context_post_apply_verifier.py").write_text(
"telegram_alert_learning_context_post_apply_verifier_v1\n",
encoding="utf-8",
)
proof = _inspect_source_contract(tmp_path)
@@ -158,6 +169,8 @@ def test_telegram_matrix_source_contract_supports_container_layout(tmp_path):
assert proof["ai_alert_card_ai_agent_context_ref_present"] is True
assert proof["telegram_alert_ai_loop_consumer_context_readback_present"] is True
assert proof["telegram_alert_ai_loop_consumer_context_readback_count"] == 1
assert proof["telegram_alert_post_apply_verifier_readback_present"] is True
assert proof["telegram_alert_post_apply_verifier_readback_count"] == 1
def test_telegram_alert_ai_automation_matrix_endpoint_returns_readback():

View File

@@ -0,0 +1,184 @@
from __future__ import annotations
import json
from fastapi import FastAPI
from fastapi.testclient import TestClient
from src.api.v1 import agents
from src.api.v1.agents import router
from src.services.telegram_alert_learning_context_post_apply_verifier import (
build_telegram_alert_learning_context_post_apply_verifier,
)
def _context_receipts() -> list[dict]:
targets = [
("km", "knowledge_memory_context"),
("rag", "rag_index_candidate_context"),
("playbook", "playbook_trust_candidate_context"),
("mcp", "mcp_audit_feedback_context"),
("verifier", "post_apply_verifier_feedback_context"),
("ai_agent", "autonomous_runtime_decision_context"),
]
return [
{
"receipt_id": f"telegram_alert_learning_context::msg-telegram-1::{target}",
"source_receipt_id": "msg-telegram-1",
"source_run_id": "run-telegram-1",
"source_message_id": "msg-telegram-1",
"work_item_id": "CIR-P0-TG-001",
"target": target,
"consumer_surface": surface,
"source_ref": f"{target}://awoooi/telegram-alert/msg-telegram-1",
"ai_agent_context_ref": (
"ai-agent://awoooi/telegram-alert-learning-context/"
"run-telegram-1/msg-telegram-1"
),
"status": "ready_for_ai_loop_context",
"metadata_only": True,
"target_write_performed": False,
"raw_payload_included": False,
"target_selector": {
"project_id": "awoooi",
"run_id": "run-telegram-1",
"message_id": "msg-telegram-1",
"target": target,
"source_ref": f"{target}://awoooi/telegram-alert/msg-telegram-1",
},
"source_of_truth_diff": {
"current_state": "telegram_alert_learning_registry_readable",
"desired_state": "ai_loop_agent_context_receipt_available",
"delta_kind": f"telegram_alert_{target}_context_binding",
"raw_payload_included": False,
},
"check_mode": {
"enabled": True,
"checks": [
"ai_alert_card_delivery_receipt_present",
"learning_registry_binding_ready",
"metadata_only_raw_payload_absent",
"ai_agent_context_ref_present",
],
},
"rollback": {
"required": True,
"rollback_ref": (
"rollback://telegram-alert-learning-context/"
f"msg-telegram-1/{target}"
),
},
"post_apply_verifier": {
"required": True,
"verifier_refs": [
"verifier://awoooi/telegram-alert-delivery-receipt/run-telegram-1",
f"{target}://awoooi/telegram-alert/msg-telegram-1",
],
},
}
for target, surface in targets
]
def _consumer_readback(*, receipts: list[dict] | None = None) -> dict:
return {
"schema_version": "ai_agent_log_controlled_writeback_consumer_readback_v1",
"status": "controlled_writeback_consumer_readback_ready",
"telegram_alert_learning_context": {
"schema_version": "telegram_alert_ai_loop_consumer_context_readback_v1",
"status": "ai_loop_agent_context_receipt_ready",
"project_id": "awoooi",
"source_registry_status": "learning_registry_ready",
"consumer_context_route": "ai_loop_agent.telegram_alert_learning_context",
"target_count": 6,
"ready_target_count": 6,
"context_receipt_count": 6,
"ai_agent_context_receipt_count": 1,
"context_receipts": receipts if receipts is not None else _context_receipts(),
},
}
def test_telegram_alert_learning_context_post_apply_verifier_passes_receipts():
payload = build_telegram_alert_learning_context_post_apply_verifier(
consumer_readback=_consumer_readback()
)
assert payload["schema_version"] == (
"telegram_alert_learning_context_post_apply_verifier_v1"
)
assert payload["status"] == (
"telegram_alert_learning_context_post_apply_verified"
)
assert payload["active_blockers"] == []
assert payload["controlled_verifier"]["post_apply_verifier_executed"] is True
assert payload["controlled_verifier"]["raw_payload_absence_verified"] is True
assert payload["operation_boundaries"]["runtime_target_write_performed"] is False
assert payload["operation_boundaries"]["telegram_send_performed"] is False
assert payload["operation_boundaries"]["secret_value_collection_allowed"] is False
rollups = payload["rollups"]
assert rollups["telegram_alert_learning_context_post_apply_verifier_ready"] is True
assert rollups["context_receipt_count"] == 6
assert rollups["verified_context_receipt_count"] == 6
assert rollups["verified_target_count"] == 6
assert rollups["verified_ai_agent_context_receipt_count"] == 1
assert rollups["raw_payload_included_count"] == 0
assert rollups["runtime_write_performed_count"] == 0
ai_agent_result = [
result
for result in payload["verifier_results"]
if result["target"] == "ai_agent"
][0]
assert ai_agent_result["verifier_status"] == "passed"
assert ai_agent_result["target_selector_verified"] is True
assert ai_agent_result["rollback_verified"] is True
assert ai_agent_result["post_apply_verifier_refs"]
serialized = json.dumps(payload, ensure_ascii=False)
assert "TELEGRAM_BOT_TOKEN" not in serialized
assert "raw Telegram payload" not in serialized
def test_telegram_alert_learning_context_post_apply_verifier_blocks_bad_receipt():
receipts = _context_receipts()
receipts[0]["rollback"] = {"required": True, "rollback_ref": ""}
payload = build_telegram_alert_learning_context_post_apply_verifier(
consumer_readback=_consumer_readback(receipts=receipts)
)
assert payload["status"] == (
"blocked_telegram_alert_learning_context_post_apply_verifier"
)
assert payload["rollups"]["failed_context_receipt_count"] == 1
assert any(
blocker.startswith("telegram_alert_context_receipt_verifier_failed:")
for blocker in payload["active_blockers"]
)
def test_telegram_alert_learning_context_post_apply_verifier_endpoint(monkeypatch):
async def fake_loader():
return build_telegram_alert_learning_context_post_apply_verifier(
consumer_readback=_consumer_readback()
)
monkeypatch.setattr(
agents,
"load_latest_telegram_alert_learning_context_post_apply_verifier",
fake_loader,
)
app = FastAPI()
app.include_router(router, prefix="/api/v1")
client = TestClient(app)
response = client.get(
"/api/v1/agents/telegram-alert-learning-context-post-apply-verifier"
)
assert response.status_code == 200
data = response.json()
assert data["status"] == "telegram_alert_learning_context_post_apply_verified"
assert data["rollups"]["verified_target_count"] == 6