chore(kb): notițe youtube mai, fix email tools, update newsletter/anaf-monitor

Adaugă 4 notițe YouTube (llama.cpp, Mario Zechner, bonificatie impozit,
AI scaffolding) + notă coaching grok. Actualizează index KB.
Fix email_digest și email_forward. Update newsletter cercetasi + cron jobs.
ANAF monitor hashes/snapshots/versions la zi.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-13 21:02:55 +00:00
parent f04e033dbe
commit 3570d9a625
16 changed files with 676 additions and 72 deletions

View File

@@ -96,6 +96,13 @@ def run_heartbeat(config: dict | None = None) -> str:
results.append(emb_result)
checks["embeddings"] = now.isoformat()
# Git uncommitted files alone are not an actionable alert — skip Claude too
non_git_results = [r for r in results if not r.startswith("Git:")]
if not critical and not non_git_results:
state["last_run"] = now.isoformat()
_save_state(state)
return "HEARTBEAT_OK"
# Claude CLI: run if HEARTBEAT.md has extra instructions
claude_result = _run_claude_extra(hb_config, critical + results)
if claude_result:
@@ -109,11 +116,6 @@ def run_heartbeat(config: dict | None = None) -> str:
if not all_results:
return "HEARTBEAT_OK"
# Git uncommitted files alone are not an actionable alert — stay silent
non_git = [r for r in all_results if not r.startswith("Git:")]
if not non_git:
return "HEARTBEAT_OK"
return " | ".join(all_results)

View File

@@ -127,12 +127,29 @@ async def check_and_send(config, send_callback) -> None:
return
channel = config.get("newsletter_cercetasi.channel", "echo-core")
sent = False
try:
await send_callback(channel, summary)
sent = True
log.info("Newsletter #%d/%d summary sent to channel '%s'", next_n, current_year, channel)
except Exception as e:
log.error("Send failed for newsletter #%d/%d — will retry next check: %s", next_n, current_year, e)
# Trimite și pe WhatsApp dacă e configurat
owner = config.get("whatsapp.owner", "")
if owner and sent:
owner_jid = f"{owner}@s.whatsapp.net"
bridge_url = config.get("whatsapp.bridge_url", "http://127.0.0.1:8098")
try:
async with httpx.AsyncClient() as client:
for chunk in [summary[i:i+4096] for i in range(0, len(summary), 4096)]:
await client.post(f"{bridge_url}/send", json={"to": owner_jid, "text": chunk}, timeout=15)
log.info("Newsletter #%d/%d summary sent to WhatsApp", next_n, current_year)
except Exception as e:
log.error("WhatsApp send failed for newsletter #%d/%d: %s", next_n, current_year, e)
if sent:
state["last_sent"] = next_n
state["year"] = current_year
state["last_sent_at"] = datetime.now(timezone.utc).isoformat()
_write_state(state)
log.info("Newsletter #%d/%d summary sent to channel '%s'", next_n, current_year, channel)
except Exception as e:
log.error("Send failed for newsletter #%d/%d — will retry next check: %s", next_n, current_year, e)