feat(ai): automate agent integration truth and RAG canary
Some checks failed
CD Pipeline / deploy (push) Has been cancelled

This commit is contained in:
ogt
2026-07-17 02:00:35 +08:00
parent b51449b96c
commit 81b99f12b3
16 changed files with 1977 additions and 10 deletions

View File

@@ -9,7 +9,7 @@ run_scheduler.py — momo-scheduler 容器入口點
每 6 小時pchome_growth_yahoo_backfill、quality_rescore、action_plan_hygiene
每 12 小時dedup_batch
每 10 分鐘ppt_auto_generation_catchup補跑被長任務卡過的定期簡報
每 1 天 db_backup03:00、cleanup_agent_context03:30、backup_monitor04:00、daily_report09:00、roi_monthly_report gate09:05、ai_smoke_summary09:10、observability_daily_summary09:30、pchome_match_backfill10:30、pchome_growth_momo_backfill10:45、openclaw_meta_analysis12:00, Phase 4 降頻、ppt_auto_generation_daily20:30、ppt_vision_audit22:00、daily_token_report23:55
每 1 天 db_backup03:00、cleanup_agent_context03:30、backup_monitor04:00internal_rag_candidate_canary04:45daily_report09:00、roi_monthly_report gate09:05、ai_smoke_summary09:10、observability_daily_summary09:30、pchome_match_backfill10:30、pchome_growth_momo_backfill10:45、openclaw_meta_analysis12:00, Phase 4 降頻、ppt_auto_generation_daily20:30、ppt_vision_audit22:00、daily_token_report23:55
每 1 週 weekly_strategy週一 06:00、ppt_auto_generation_weekly週一 20:40
每 1 月 monthly_report每月1日 07:00、ppt_auto_generation_monthly每月1日 20:50
每 1 季 ppt_auto_generation_quarterly1/4/7/10 月 1 日 21:00
@@ -283,6 +283,121 @@ def _notify_scheduler_failure(
logger.error("[%s] event_router notify failed: %s", task_name, router_error)
def run_internal_rag_candidate_canary_task() -> dict[str, object]:
"""Run one scheduled PixelRAG-to-pgvector canary with durable acknowledgements."""
if not _env_flag("INTERNAL_RAG_CANDIDATE_CANARY_SCHEDULED_ENABLED", True):
payload: dict[str, object] = {
"success": True,
"status": "skipped",
"terminal_status": "no_write_terminal",
"reason": "scheduled_canary_disabled_by_policy",
"next_machine_action": "enable_scheduled_canary_after_policy_review",
}
_save_stats("internal_rag_candidate_canary", payload)
return payload
try:
from services.internal_rag_candidate_canary_service import (
run_internal_rag_candidate_canary,
)
from services.telegram_templates import send_telegram_with_result
payload = run_internal_rag_candidate_canary(
limit=1,
execute=True,
write_receipt=True,
)
summary = payload.get("summary") or {}
telegram = send_telegram_with_result(
"\n".join([
"Internal RAG candidate canary",
f"status: {payload.get('status')}",
f"source: {summary.get('source_receipt_count', 0)}",
f"executed: {summary.get('executed_count', 0)}",
f"passed: {summary.get('canary_passed_count', 0)}",
f"next: {payload.get('next_machine_action')}",
f"run_id: {(payload.get('run_identity') or {}).get('run_id')}",
]),
parse_mode=None,
)
telegram_ack = "acknowledged" if telegram.get("ok") else "failed"
rag_ack = (
"rag_canary_receipt_written"
if int(summary.get("executed_count") or 0) > 0
else "no_write_terminal"
)
payload["acknowledgements"] = {
"telegram": {
"status": telegram_ack,
"sent": int(telegram.get("sent") or 0),
"failed": int(telegram.get("failed") or 0),
},
"km": "not_applicable_no_incident",
"rag": rag_ack,
"mcp": "not_applicable_no_mcp_call",
"playbook": "not_applicable_no_incident",
}
closure = payload.setdefault("closure_receipt", {})
closure["telegram_acknowledgement"] = telegram_ack
closure["learning_write_acknowledgement"] = rag_ack
if payload.get("status") in {"canary_failed", "blocked"} or telegram_ack == "failed":
payload["terminal_status"] = "partial"
elif payload.get("status") == "warning":
payload["terminal_status"] = "no_write_terminal"
elif payload.get("status") == "canary_passed_activation_blocked":
payload["terminal_status"] = "verified_with_activation_blocker"
else:
payload["terminal_status"] = "verified"
_save_stats("internal_rag_candidate_canary", payload)
logger.info(
"[InternalRAGCanary] status=%s terminal=%s executed=%s passed=%s telegram=%s",
payload.get("status"),
payload.get("terminal_status"),
summary.get("executed_count", 0),
summary.get("canary_passed_count", 0),
telegram_ack,
)
if payload.get("status") == "canary_failed":
_notify_scheduler_failure(
"run_internal_rag_candidate_canary_task",
RuntimeError("internal RAG candidate canary failed"),
source="Scheduler.InternalRAGCanary",
event_type="internal_rag_candidate_canary_failure",
title="Internal RAG candidate canary failed",
dedup_ttl_sec=86400,
)
elif telegram_ack == "failed":
_notify_scheduler_failure(
"run_internal_rag_candidate_canary_task",
RuntimeError("internal RAG canary Telegram acknowledgement failed"),
source="Scheduler.InternalRAGCanary",
event_type="internal_rag_candidate_canary_ack_failure",
title="Internal RAG canary acknowledgement failed",
dedup_ttl_sec=86400,
)
return payload
except Exception as error:
logger.error("[InternalRAGCanary] task failed: %s", error, exc_info=True)
_notify_scheduler_failure(
"run_internal_rag_candidate_canary_task",
error,
source="Scheduler.InternalRAGCanary",
event_type="internal_rag_candidate_canary_task_failure",
title="Internal RAG candidate canary task failed",
dedup_ttl_sec=86400,
)
payload = {
"success": False,
"status": "failed",
"terminal_status": "partial",
"error": f"{type(error).__name__}: {str(error)[:300]}",
"next_machine_action": "inspect_canary_receipt_and_retry_bounded_run",
}
_save_stats("internal_rag_candidate_canary", payload)
return payload
def _register_schedules():
schedule.every(30).minutes.do(run_revenue_automation_cycle_background_task)
logger.info("📅 每 30 分鐘revenue_automation_cycle業績匯入 → 比價回填,非阻塞)")
@@ -464,6 +579,9 @@ def _register_schedules():
schedule.every().day.at("04:15").do(run_codebase_modularization_performance_task)
logger.info("📅 每日 04:15codebase_modularization_performance inventory")
schedule.every().day.at("04:45").do(run_internal_rag_candidate_canary_task)
logger.info("📅 每日 04:45internal_rag_candidate_canarybounded read-only probe")
schedule.every().monday.at("06:00").do(run_weekly_strategy_task)
logger.info("📅 每週一 06:00weekly_strategy")