feat(api): plan controlled log writeback
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 1m7s
CD Pipeline / build-and-deploy (push) Has been skipped
CD Pipeline / post-deploy-checks (push) Has been skipped
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 1m7s
CD Pipeline / build-and-deploy (push) Has been skipped
CD Pipeline / post-deploy-checks (push) Has been skipped
This commit is contained in:
@@ -0,0 +1,273 @@
|
||||
"""AI Agent LOG controlled writeback plan readback.
|
||||
|
||||
Builds the machine-readable target selectors, source-of-truth diffs,
|
||||
check-mode gates, rollback refs, and post-apply verifier refs needed to turn
|
||||
verified LOG feedback receipts into a controlled KM / RAG / PlayBook / MCP /
|
||||
AI Agent writeback lane. This module prepares the apply plan only; it does not
|
||||
perform writes, call MCP tools, trigger workflows, or persist raw log payloads.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from src.services.ai_agent_log_feedback_receipt_dry_run import (
|
||||
load_latest_ai_agent_log_feedback_receipt_dry_run,
|
||||
)
|
||||
from src.services.ai_agent_log_post_write_verifier_dry_run import (
|
||||
load_latest_ai_agent_log_post_write_verifier_dry_run,
|
||||
)
|
||||
|
||||
_SCHEMA_VERSION = "ai_agent_log_controlled_writeback_plan_readback_v1"
|
||||
_VERIFIER_READY_STATUS = "post_write_verifier_dry_run_ready"
|
||||
_FEEDBACK_READY_STATUS = "trusted_feedback_receipt_dry_run_ready"
|
||||
_TARGETS = ("km", "rag", "playbook", "mcp", "verifier", "ai_agent")
|
||||
|
||||
|
||||
def load_latest_ai_agent_log_controlled_writeback_plan_readback() -> dict[str, Any]:
|
||||
"""Return a controlled apply plan for verified LOG feedback receipts."""
|
||||
verifier = load_latest_ai_agent_log_post_write_verifier_dry_run()
|
||||
feedback = load_latest_ai_agent_log_feedback_receipt_dry_run()
|
||||
receipts = _candidate_receipts(feedback)
|
||||
verifier_ready = (
|
||||
verifier.get("status") == _VERIFIER_READY_STATUS
|
||||
and verifier.get("active_blockers") == []
|
||||
and (verifier.get("rollups") or {}).get("controlled_writeback_next_step_ready")
|
||||
is True
|
||||
)
|
||||
feedback_ready = (
|
||||
feedback.get("status") == _FEEDBACK_READY_STATUS
|
||||
and feedback.get("active_blockers") == []
|
||||
and (feedback.get("rollups") or {}).get("dry_run_ready") is True
|
||||
)
|
||||
writeback_plans = _writeback_plans(receipts)
|
||||
active_blockers = _active_blockers(
|
||||
verifier_ready=verifier_ready,
|
||||
feedback_ready=feedback_ready,
|
||||
receipts=receipts,
|
||||
writeback_plans=writeback_plans,
|
||||
)
|
||||
|
||||
return {
|
||||
"schema_version": _SCHEMA_VERSION,
|
||||
"priority": "P1-LOG-KM-RAG-MCP-PLAYBOOK",
|
||||
"scope": "ai_agent_log_controlled_writeback_plan",
|
||||
"status": (
|
||||
"controlled_writeback_plan_ready"
|
||||
if not active_blockers
|
||||
else "blocked_waiting_controlled_writeback_plan_inputs"
|
||||
),
|
||||
"readback": {
|
||||
"workplan_id": "P1-LOG-CONTROLLED-WRITEBACK-PLAN",
|
||||
"workplan_title": "LOG feedback controlled KM / RAG / MCP / PlayBook / AI Agent writeback plan",
|
||||
"feedback_schema_version": feedback.get("schema_version"),
|
||||
"feedback_status": feedback.get("status"),
|
||||
"verifier_schema_version": verifier.get("schema_version"),
|
||||
"verifier_status": verifier.get("status"),
|
||||
"safe_next_step": "execute_controlled_writeback_apply_with_post_apply_verifier",
|
||||
},
|
||||
"controlled_apply": {
|
||||
"mode": "controlled_apply_prepared",
|
||||
"target_selector_required": True,
|
||||
"source_of_truth_diff_required": True,
|
||||
"check_mode_required": True,
|
||||
"rollback_required": True,
|
||||
"post_apply_verifier_required": True,
|
||||
"owner_review_required_for_low_medium_high": False,
|
||||
"critical_break_glass_required": True,
|
||||
},
|
||||
"writeback_plans": writeback_plans,
|
||||
"target_rollups": _target_rollups(writeback_plans),
|
||||
"rollups": {
|
||||
"target_count": len(_TARGETS),
|
||||
"candidate_receipt_count": len(receipts),
|
||||
"writeback_plan_count": len(writeback_plans),
|
||||
"ready_writeback_plan_count": sum(
|
||||
1 for plan in writeback_plans if plan["status"] == "controlled_apply_ready"
|
||||
),
|
||||
"check_mode_plan_count": sum(
|
||||
1 for plan in writeback_plans if plan["check_mode"]["enabled"] is True
|
||||
),
|
||||
"rollback_plan_count": sum(
|
||||
1 for plan in writeback_plans if plan["rollback"]["required"] is True
|
||||
),
|
||||
"post_apply_verifier_plan_count": sum(
|
||||
1
|
||||
for plan in writeback_plans
|
||||
if plan["post_apply_verifier"]["required"] is True
|
||||
),
|
||||
"controlled_writeback_plan_ready": not active_blockers,
|
||||
"runtime_write_performed": False,
|
||||
},
|
||||
"active_blockers": active_blockers,
|
||||
"operation_boundaries": {
|
||||
"plan_readback_only": True,
|
||||
"km_write_performed": False,
|
||||
"rag_index_write_performed": False,
|
||||
"playbook_trust_write_performed": False,
|
||||
"mcp_tool_call_performed": False,
|
||||
"agent_runtime_action_performed": False,
|
||||
"workflow_trigger_performed": False,
|
||||
"raw_log_payload_persisted": False,
|
||||
"secret_value_collection_allowed": False,
|
||||
"github_api_used": False,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def _candidate_receipts(feedback: dict[str, Any]) -> list[dict[str, Any]]:
|
||||
receipts = feedback.get("candidate_receipts")
|
||||
if not isinstance(receipts, list):
|
||||
return []
|
||||
return [receipt for receipt in receipts if isinstance(receipt, dict)]
|
||||
|
||||
|
||||
def _writeback_plans(receipts: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
||||
plans = []
|
||||
for receipt in receipts:
|
||||
target = str(receipt.get("target") or "")
|
||||
source_sample_id = str(receipt.get("source_sample_id") or "")
|
||||
receipt_id = str(receipt.get("receipt_id") or "")
|
||||
plan_id = f"log-feedback-writeback::{target}::{source_sample_id}"
|
||||
plans.append(
|
||||
{
|
||||
"plan_id": plan_id,
|
||||
"receipt_id": receipt_id,
|
||||
"target": target,
|
||||
"status": "controlled_apply_ready",
|
||||
"risk_tier": "medium" if target in {"km", "rag", "playbook"} else "low",
|
||||
"target_selector": {
|
||||
"project_id": receipt.get("project_id"),
|
||||
"product": receipt.get("product"),
|
||||
"service": receipt.get("service"),
|
||||
"package": receipt.get("package"),
|
||||
"tool": receipt.get("tool"),
|
||||
"source_system": receipt.get("source_system"),
|
||||
"source_sample_id": source_sample_id,
|
||||
"target_surface": _target_surface(target),
|
||||
},
|
||||
"source_of_truth_diff": {
|
||||
"current_state": "metadata_only_feedback_not_written",
|
||||
"desired_state": "metadata_only_feedback_receipt_bound_to_target",
|
||||
"delta_kind": _delta_kind(target),
|
||||
"raw_payload_included": False,
|
||||
"redaction_state": receipt.get("redaction_state"),
|
||||
"observed_event_count": receipt.get("observed_event_count"),
|
||||
"observed_field_count": receipt.get("observed_field_count"),
|
||||
},
|
||||
"check_mode": {
|
||||
"enabled": True,
|
||||
"checks": [
|
||||
"target_selector_resolves_single_surface",
|
||||
"metadata_only_redaction_state",
|
||||
"raw_log_payload_absent",
|
||||
"post_apply_verifier_ref_present",
|
||||
],
|
||||
},
|
||||
"rollback": {
|
||||
"required": True,
|
||||
"rollback_ref": f"rollback://ai-agent-log-feedback/{target}/{source_sample_id}",
|
||||
"strategy": "mark_receipt_superseded_and_remove_target_binding",
|
||||
},
|
||||
"post_apply_verifier": {
|
||||
"required": True,
|
||||
"verifier_ref": f"post-write-verifier://ai-agent-log-feedback/{target}/{source_sample_id}",
|
||||
"canonical_readback": (
|
||||
"/api/v1/agents/agent-log-controlled-writeback-plan-readback"
|
||||
),
|
||||
},
|
||||
"write_enabled_by_plan": False,
|
||||
}
|
||||
)
|
||||
return plans
|
||||
|
||||
|
||||
def _target_rollups(plans: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
||||
return [
|
||||
{
|
||||
"target": target,
|
||||
"plan_count": sum(1 for plan in plans if plan.get("target") == target),
|
||||
"ready_plan_count": sum(
|
||||
1
|
||||
for plan in plans
|
||||
if plan.get("target") == target
|
||||
and plan.get("status") == "controlled_apply_ready"
|
||||
),
|
||||
"check_mode_ready": all(
|
||||
plan.get("check_mode", {}).get("enabled") is True
|
||||
for plan in plans
|
||||
if plan.get("target") == target
|
||||
),
|
||||
"rollback_ready": all(
|
||||
plan.get("rollback", {}).get("required") is True
|
||||
for plan in plans
|
||||
if plan.get("target") == target
|
||||
),
|
||||
"post_apply_verifier_ready": all(
|
||||
plan.get("post_apply_verifier", {}).get("required") is True
|
||||
for plan in plans
|
||||
if plan.get("target") == target
|
||||
),
|
||||
}
|
||||
for target in _TARGETS
|
||||
]
|
||||
|
||||
|
||||
def _active_blockers(
|
||||
*,
|
||||
verifier_ready: bool,
|
||||
feedback_ready: bool,
|
||||
receipts: list[dict[str, Any]],
|
||||
writeback_plans: list[dict[str, Any]],
|
||||
) -> list[str]:
|
||||
blockers = []
|
||||
if not verifier_ready:
|
||||
blockers.append("post_write_verifier_dry_run_not_ready")
|
||||
if not feedback_ready:
|
||||
blockers.append("feedback_receipt_dry_run_not_ready")
|
||||
if not receipts:
|
||||
blockers.append("candidate_receipts_missing")
|
||||
if len(writeback_plans) != len(receipts):
|
||||
blockers.append("writeback_plan_count_mismatch")
|
||||
for target in _TARGETS:
|
||||
if not any(plan.get("target") == target for plan in writeback_plans):
|
||||
blockers.append(f"{target}_writeback_plan_missing")
|
||||
for plan in writeback_plans:
|
||||
if plan.get("write_enabled_by_plan") is not False:
|
||||
blockers.append(f"{plan.get('plan_id')}:write_enabled_by_plan_not_false")
|
||||
if plan.get("source_of_truth_diff", {}).get("raw_payload_included") is not False:
|
||||
blockers.append(f"{plan.get('plan_id')}:raw_payload_included")
|
||||
return _unique(blockers)
|
||||
|
||||
|
||||
def _target_surface(target: str) -> str:
|
||||
return {
|
||||
"km": "knowledge_memory",
|
||||
"rag": "rag_chunk_index",
|
||||
"playbook": "playbook_trust_learning",
|
||||
"mcp": "mcp_audit_context",
|
||||
"verifier": "post_apply_verifier_feedback",
|
||||
"ai_agent": "agent_decision_context",
|
||||
}.get(target, "unknown")
|
||||
|
||||
|
||||
def _delta_kind(target: str) -> str:
|
||||
return {
|
||||
"km": "append_km_memory_receipt",
|
||||
"rag": "index_metadata_only_rag_chunk",
|
||||
"playbook": "append_playbook_trust_signal",
|
||||
"mcp": "append_mcp_audit_feedback",
|
||||
"verifier": "append_post_apply_verifier_feedback",
|
||||
"ai_agent": "publish_agent_context_receipt",
|
||||
}.get(target, "unknown")
|
||||
|
||||
|
||||
def _unique(values: list[str]) -> list[str]:
|
||||
seen = set()
|
||||
result = []
|
||||
for value in values:
|
||||
if value in seen:
|
||||
continue
|
||||
seen.add(value)
|
||||
result.append(value)
|
||||
return result
|
||||
Reference in New Issue
Block a user