新增 PChome compact controlled apply readback
Some checks failed
CD Pipeline / deploy (push) Has been cancelled

This commit is contained in:
ogt
2026-07-02 13:28:40 +08:00
parent 99df3b9a76
commit f1795e555d
5 changed files with 376 additions and 4 deletions

View File

@@ -80,6 +80,9 @@ DIRECT_MAPPING_RETRY_CANDIDATE_EXCEPTION_CONTROLLED_APPLY_DRIFT_VERIFIER_POLICY
DIRECT_MAPPING_RETRY_CANDIDATE_EXCEPTION_CONTROLLED_APPLY_DRIFT_RECOVERY_POLICY = (
"ai_controlled_pchome_growth_direct_mapping_retry_candidate_exception_controlled_apply_drift_recovery"
)
DIRECT_MAPPING_RETRY_CANDIDATE_EXCEPTION_CONTROLLED_APPLY_COMPACT_READBACK_POLICY = (
"read_only_pchome_growth_direct_mapping_retry_candidate_exception_controlled_apply_compact_readback"
)
AI_AUTOMATION_READINESS_POLICY = "read_only_pchome_growth_ai_automation_readiness"
EVIDENCE_ENRICHMENT_PREVIEW_POLICY = "read_only_pchome_growth_evidence_enrichment_preview"
EVIDENCE_SOURCE_PREVIEW_POLICY = "read_only_pchome_growth_evidence_source_preview"
@@ -4982,6 +4985,296 @@ def build_pchome_direct_mapping_retry_candidate_exception_controlled_apply_drift
}
def _compact_retry_exception_artifact_readback(
root: Path,
subdir: str,
*,
artifact_key: str,
run_id: str | None = None,
) -> dict[str, Any]:
path = _find_retry_exception_artifact_file(root, subdir, run_id)
payload = _load_retry_exception_json_artifact(path)
actual_sha = hashlib.sha256(path.read_bytes()).hexdigest() if path and path.exists() else ""
return {
"artifact_key": artifact_key,
"exists": bool(path and path.exists()),
"relative_path": str(path.relative_to(root)) if path and path.exists() else None,
"absolute_path": str(path) if path and path.exists() else None,
"payload_sha256": actual_sha,
"byte_count": path.stat().st_size if path and path.exists() else 0,
"result": payload.get("result"),
"run_id": payload.get("run_id"),
"summary": payload.get("summary") or {},
"writes_database": False,
}
def _compact_package_artifact_readback(package: dict[str, Any], artifact_key: str) -> dict[str, Any]:
artifact = (
package.get("executor_receipt_artifact")
or package.get("drift_verifier_artifact")
or package.get("recovery_artifact")
or {}
)
verifier = (
package.get("post_executor_receipt_verifier")
or package.get("post_drift_verifier_artifact_verifier")
or package.get("post_recovery_artifact_verifier")
or {}
)
return {
"artifact_key": artifact_key,
"exists": bool(verifier.get("actual_sha256")),
"relative_path": artifact.get("relative_path"),
"payload_sha256": verifier.get("actual_sha256") or artifact.get("payload_sha256") or "",
"expected_sha256": verifier.get("expected_sha256") or artifact.get("payload_sha256") or "",
"hash_match": bool(verifier.get("hash_match")),
"byte_count": artifact.get("byte_count") or 0,
"result": package.get("result"),
"summary": package.get("summary") or {},
"writes_database": False,
}
def build_pchome_direct_mapping_retry_candidate_exception_controlled_apply_compact_readback_package(
*,
artifact_root: str | Path | None = None,
run_id: str | None = None,
engine: Any = None,
source_receipt_replay: dict[str, Any] | None = None,
source_drift_verifier: dict[str, Any] | None = None,
source_drift_recovery: dict[str, Any] | None = None,
materialize_artifacts: bool = False,
) -> dict[str, Any]:
"""Build a compact product-facing readback for apply / replay / drift / recovery receipts."""
root = Path(artifact_root) if artifact_root is not None else Path.cwd() / "data"
apply_receipt = _compact_retry_exception_artifact_readback(
root,
"controlled_apply_executor",
artifact_key="retry_exception_controlled_apply_executor_receipt",
run_id=run_id,
)
replay = source_receipt_replay or build_pchome_direct_mapping_retry_candidate_exception_controlled_apply_receipt_replay_package(
artifact_root=root,
run_id=run_id,
materialize_artifacts=False,
engine=engine,
)
drift = source_drift_verifier or build_pchome_direct_mapping_retry_candidate_exception_controlled_apply_drift_verifier_package(
artifact_root=root,
run_id=run_id,
engine=engine,
source_receipt_replay=replay,
materialize_artifacts=False,
)
recovery = source_drift_recovery or build_pchome_direct_mapping_retry_candidate_exception_controlled_apply_drift_recovery_package(
artifact_root=root,
run_id=run_id,
engine=engine,
source_receipt_replay=replay,
source_drift_verifier=drift,
materialize_artifacts=False,
)
replay_summary = replay.get("summary") or {}
drift_summary = drift.get("summary") or {}
recovery_summary = recovery.get("summary") or {}
selector_count = int(drift_summary.get("target_selector_count") or replay_summary.get("target_selector_count") or 0)
readback_pass_count = int(
drift_summary.get("post_apply_readback_pass_count")
or replay_summary.get("post_apply_readback_pass_count")
or 0
)
drift_count = int(drift_summary.get("drift_count") or 0)
recovery_action_count = int(recovery_summary.get("drift_recovery_action_count") or 0)
replay_hash_match_count = int(replay_summary.get("executor_receipt_hash_match_count") or 0)
drift_hash_match_count = int(drift_summary.get("drift_verifier_artifact_hash_match_count") or 0)
recovery_hash_match_count = int(recovery_summary.get("recovery_artifact_hash_match_count") or 0)
apply_hash_match_count = 1 if apply_receipt.get("exists") and len(str(apply_receipt.get("payload_sha256") or "")) == 64 else 0
if drift_count:
result = "DIRECT_MAPPING_RETRY_EXCEPTION_CONTROLLED_APPLY_COMPACT_READBACK_DRIFT_REQUIRES_RECOVERY"
next_machine_action = "run_controlled_reapply_check_mode"
product_status = "blocked"
elif (
selector_count
and readback_pass_count == selector_count
and replay_hash_match_count
and drift.get("result") == "DIRECT_MAPPING_RETRY_EXCEPTION_CONTROLLED_APPLY_DRIFT_VERIFIED"
and recovery.get("result") == "DIRECT_MAPPING_RETRY_EXCEPTION_CONTROLLED_APPLY_DRIFT_RECOVERY_NOT_REQUIRED"
):
result = "DIRECT_MAPPING_RETRY_EXCEPTION_CONTROLLED_APPLY_COMPACT_READBACK_VERIFIED"
next_machine_action = "keep_monitoring_drift"
product_status = "completed"
elif replay.get("missing_artifacts"):
result = "WAITING_FOR_RETRY_EXCEPTION_CONTROLLED_APPLY_COMPACT_READBACK_ARTIFACTS"
next_machine_action = "restore_or_materialize_source_receipts"
product_status = "waiting"
else:
result = "WAITING_FOR_RETRY_EXCEPTION_CONTROLLED_APPLY_COMPACT_READBACK_BASELINE"
next_machine_action = "run_receipt_replay_and_drift_verifier"
product_status = "waiting"
summary = {
"target_selector_count": selector_count,
"post_apply_readback_pass_count": readback_pass_count,
"post_apply_readback_fail_count": max(selector_count - readback_pass_count, 0),
"drift_count": drift_count,
"drift_recovery_action_count": recovery_action_count,
"drift_reapply_ready_count": int(recovery_summary.get("drift_reapply_ready_count") or 0),
"apply_receipt_hash_match_count": apply_hash_match_count,
"replay_receipt_hash_match_count": replay_hash_match_count,
"drift_verifier_artifact_hash_match_count": drift_hash_match_count,
"recovery_artifact_hash_match_count": recovery_hash_match_count,
"compact_readback_artifact_materialized_count": 0,
"compact_readback_artifact_hash_match_count": 0,
"writes_database_count": 0,
}
receipts = {
"apply": apply_receipt,
"replay": _compact_package_artifact_readback(
replay,
"retry_exception_controlled_apply_executor_replay_receipt",
),
"drift": _compact_package_artifact_readback(
drift,
"retry_exception_controlled_apply_drift_verifier_receipt",
),
"recovery": _compact_package_artifact_readback(
recovery,
"retry_exception_controlled_apply_drift_recovery_receipt",
),
}
safety = {
"ai_controlled_apply": True,
"compact_readback": True,
"reads_artifact_files": True,
"reads_database": engine is not None,
"writes_database": False,
"writes_database_count": 0,
"writes_artifact_count": 0,
"syncs_external_offers": False,
"dispatches_telegram": False,
"gemini_allowed": False,
"requires_production_version_truth": True,
}
compact_id_payload = {
"run_id": run_id or (replay.get("receipt_replay") or {}).get("run_id") or "",
"result": result,
"summary": summary,
"receipts": receipts,
}
compact_id = (
"pchome-retry-exception-controlled-apply-compact-readback-"
+ hashlib.sha256(
json.dumps(compact_id_payload, ensure_ascii=False, sort_keys=True, default=str).encode("utf-8")
).hexdigest()[:16]
)
checks = [
{
"check": "apply_receipt_loaded_if_available",
"passed": bool(apply_receipt.get("exists")) or replay_hash_match_count > 0,
},
{"check": "receipt_replay_loaded", "passed": bool(replay)},
{"check": "drift_verifier_loaded", "passed": bool(drift)},
{"check": "drift_recovery_loaded", "passed": bool(recovery)},
{"check": "post_apply_readback_matches_selector_count", "passed": (not selector_count) or readback_pass_count == selector_count},
{"check": "compact_readback_does_not_write_database", "passed": True},
]
artifact_payload = {
"artifact_key": "retry_exception_controlled_apply_compact_readback_receipt",
"compact_readback_id": compact_id,
"source_policy": DIRECT_MAPPING_RETRY_CANDIDATE_EXCEPTION_CONTROLLED_APPLY_COMPACT_READBACK_POLICY,
"result": result,
"product_status": product_status,
"next_machine_action": next_machine_action,
"summary": summary,
"receipts": receipts,
"checks": checks,
"safety": safety,
}
artifact_bytes = _canonical_retry_exception_artifact_bytes(artifact_payload)
artifact_relative_path = (
f"artifacts/pchome_growth/retry_exception_closeout/"
f"controlled_apply_compact_readback/{compact_id}.json"
)
compact_artifact = {
"key": "retry_exception_controlled_apply_compact_readback_receipt",
"artifact_type": "controlled_apply_compact_readback_receipt",
"relative_path": artifact_relative_path,
"payload_sha256": hashlib.sha256(artifact_bytes).hexdigest(),
"byte_count": len(artifact_bytes),
"payload": artifact_payload,
"materialized": False,
"writes_database": False,
}
materialized_compact_artifacts: list[dict[str, Any]] = []
if materialize_artifacts and selector_count:
target_path = _resolve_retry_exception_artifact_path(root, artifact_relative_path)
target_path.parent.mkdir(parents=True, exist_ok=True)
target_path.write_bytes(artifact_bytes)
materialized_compact_artifacts.append({
"key": compact_artifact["key"],
"relative_path": artifact_relative_path,
"absolute_path": str(target_path),
"payload_sha256": compact_artifact["payload_sha256"],
"written_byte_count": target_path.stat().st_size,
"writes_database": False,
})
compact_artifact["materialized"] = True
compact_artifact["absolute_path"] = str(target_path)
artifact_path = _resolve_retry_exception_artifact_path(root, artifact_relative_path)
artifact_sha = hashlib.sha256(artifact_path.read_bytes()).hexdigest() if artifact_path.exists() else ""
artifact_hash_match = bool(artifact_sha) and artifact_sha == compact_artifact["payload_sha256"]
summary["compact_readback_artifact_materialized_count"] = len(materialized_compact_artifacts) or (1 if artifact_hash_match else 0)
summary["compact_readback_artifact_hash_match_count"] = 1 if artifact_hash_match else 0
safety["writes_artifact_count"] = len(materialized_compact_artifacts)
checks.extend([
{
"check": "compact_artifact_materialized_when_requested",
"passed": (not materialize_artifacts) or (selector_count > 0 and artifact_path.exists()),
},
{
"check": "compact_artifact_hash_matches_expected",
"passed": (not materialize_artifacts) or artifact_hash_match,
},
])
return {
"policy": DIRECT_MAPPING_RETRY_CANDIDATE_EXCEPTION_CONTROLLED_APPLY_COMPACT_READBACK_POLICY,
"result": result,
"success": result in {
"DIRECT_MAPPING_RETRY_EXCEPTION_CONTROLLED_APPLY_COMPACT_READBACK_VERIFIED",
"DIRECT_MAPPING_RETRY_EXCEPTION_CONTROLLED_APPLY_COMPACT_READBACK_DRIFT_REQUIRES_RECOVERY",
},
"summary": summary,
"compact_readback": {
"compact_readback_id": compact_id,
"stage": "P2_retry_exception_controlled_apply_compact_readback",
"status": product_status,
"next_machine_action": next_machine_action,
"materialize_artifacts": bool(materialize_artifacts),
"requires_production_version_truth": True,
},
"receipts": receipts,
"compact_artifact": compact_artifact,
"materialized_compact_artifacts": materialized_compact_artifacts,
"post_compact_artifact_verifier": {
"expected_sha256": compact_artifact["payload_sha256"],
"actual_sha256": artifact_sha,
"hash_match": artifact_hash_match,
"writes_database": False,
},
"checks": checks,
"check_count": len(checks),
"all_checks_passed": all(check.get("passed") is True for check in checks),
"next_actions": [
"Use this compact readback as the product/UI source for controlled apply status.",
"If drift_count is zero, continue automated drift monitoring.",
"If drift_count is positive, execute the recovery package through controlled check-mode first.",
],
"safety": safety,
}
def build_pchome_evidence_enrichment_preview(payload: dict[str, Any], batch_size: int = 5) -> dict[str, Any]:
"""Build a read-only evidence enrichment package for mapping targets."""
operator_preview = build_pchome_mapping_operator_preview(payload, batch_size=batch_size)