from pathlib import Path
p=Path('/opt/struktur/social-media-agent/publish_ready.py'); s=p.read_text()
start=s.index('def generate_package_image('); end=s.index('\n\ndef _direct_url',start)
replacement='''def generate_package_image(package_id: str, *, force: bool = False) -> dict:
"""Generate at most three Codex images and accept only a technical QA PASS."""
con = sqlite3.connect(CASES_DB); con.row_factory = sqlite3.Row
row = con.execute("SELECT * FROM publication_packages WHERE package_id=?", (package_id,)).fetchone()
if not row:
con.close(); raise ValueError("publication package not found")
package = dict(row); old_version = int(package.get("image_version") or 0)
prompt_base = fach_image_prompt(package)
prompt_ok, prompt_reason = image_relevance_gate(package, prompt_base)
if not prompt_ok:
con.execute("UPDATE publication_packages SET image_status='error',image_error=?,qa_status='failed',qa_failure_reasons=?,qa_report_json=?,updated_at=? WHERE package_id=?", (prompt_reason, prompt_reason, json.dumps({"attempts": [], "final": {"overall": "FAIL", "failure_reasons": [prompt_reason]}}, ensure_ascii=False), _now(), package_id)); con.commit(); con.close()
return {"ok": False, "status": "Bild fachlich unpassend", "error": prompt_reason, "attempts": []}
feedback: list[str] = []
attempt_reports: list[dict] = []
for attempt in range(1, 4):
prompt = prompt_base
if feedback:
prompt += " Korrigiere zwingend diese Fehler des vorherigen Versuchs: " + "; ".join(feedback) + "."
target = (BASE_DIR / "generated_visuals" / f"{package['signal_id']}_codex-image-gen-v{old_version + attempt}.png").resolve()
try:
generated = generate_with_codex(prompt, target)
qa = run_image_qa(target, _text(package.get("topic")), _text(package.get("final_text") or package.get("facebook_text")))
attempt_record = {"attempt": attempt, "path": str(target), "origin_path": generated.get("origin_path"), "sha256": generated.get("sha256"), "bytes": generated.get("bytes"), "qa": qa}
attempt_reports.append(attempt_record)
if qa_passes(qa):
now = _now(); report_json = json.dumps({"attempts": attempt_reports, "final": qa}, ensure_ascii=False)
con.execute("UPDATE publication_packages SET image_status='present',image_path=?,image_created_at=?,image_generator=?,image_version=?,image_error='',image_prompt=?,image_prompt_used=?,media_source_type='Codex built-in image_gen',media_source_ref=?,media_quality='technisch geprüft — visuelle Abnahme offen',qa_status='passed',qa_report_json=?,qa_failure_reasons='',qa_checked_at=?,human_visual_approval='offen',updated_at=? WHERE package_id=?", (str(target), now, "Codex built-in image_gen", old_version + attempt, prompt, prompt, generated["origin_path"], report_json, now, now, package_id))
con.commit(); con.close()
return {"ok": True, "status": "Bild technisch geprüft — visuelle Abnahme offen", "path": str(target), "version": old_version + attempt, "generator": "Codex built-in image_gen", "qa": qa, "attempts": attempt_reports}
feedback = qa.get("failure_reasons", []) or ["Technische Bildprüfung nicht bestanden."]
reason = "; ".join(feedback)
report_json = json.dumps({"attempts": attempt_reports, "final": qa}, ensure_ascii=False)
con.execute("UPDATE publication_packages SET image_status='error',image_path=?,image_generator='Codex built-in image_gen',image_version=?,image_error=?,media_source_type='Codex built-in image_gen',media_source_ref=?,media_quality='TECHNISCH ABGELEHNT',qa_status='failed',qa_report_json=?,qa_failure_reasons=?,qa_checked_at=?,updated_at=? WHERE package_id=?", (str(target), old_version + attempt, "Technische Bildprüfung nicht bestanden: " + reason, generated["origin_path"], report_json, reason, _now(), _now(), package_id)); con.commit()
except (CodexImageError, CodexImageQAError, OSError, ValueError) as exc:
feedback = [str(exc)]
attempt_reports.append({"attempt": attempt, "qa": {"overall": "FAIL", "failure_reasons": [str(exc)]}})
con.execute("UPDATE publication_packages SET image_status='error',image_generator='Codex built-in image_gen',image_version=?,image_error=?,media_quality='TECHNISCH ABGELEHNT',qa_status='failed',qa_report_json=?,qa_failure_reasons=?,qa_checked_at=?,updated_at=? WHERE package_id=?", (old_version + attempt, "Technische Bildprüfung nicht bestanden: " + str(exc), json.dumps({"attempts": attempt_reports, "final": {"overall": "FAIL", "failure_reasons": [str(exc)]}}, ensure_ascii=False), str(exc), _now(), package_id)); con.commit()
if attempt < 3:
continue
final_reason = "; ".join(feedback)
final_report = json.dumps({"attempts": attempt_reports, "final": {"overall": "FAIL", "failure_reasons": feedback}}, ensure_ascii=False)
con.execute("UPDATE publication_packages SET image_status='error',image_error=?,media_quality='TECHNISCH ABGELEHNT',qa_status='failed',qa_report_json=?,qa_failure_reasons=?,qa_checked_at=?,updated_at=? WHERE package_id=?", ("Kein technisch plausibles KI-Bild nach 3 Versuchen: " + final_reason, final_report, final_reason, _now(), package_id)); con.commit(); con.close()
return {"ok": False, "status": "Kein technisch plausibles KI-Bild nach 3 Versuchen", "error": final_reason, "attempts": attempt_reports}
con.close(); return {"ok": False, "status": "Kein technisch plausibles KI-Bild nach 3 Versuchen", "attempts": attempt_reports}
'''
s=s[:start]+replacement+s[end:]
p.write_text(s); print('rewrote controlled regeneration function')