feat(verify): add pending external verifier
This commit is contained in:
@@ -15,6 +15,14 @@ sudo ln -sf /root/.openclaw/workspace/second-brain/systemd/openclaw-memory-archi
|
||||
sudo systemctl daemon-reload
|
||||
```
|
||||
|
||||
Optional (verification hardening):
|
||||
|
||||
```bash
|
||||
sudo ln -sf /root/.openclaw/workspace/second-brain/systemd/openclaw-secondbrain-verify-pending.* /etc/systemd/system/
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable --now openclaw-secondbrain-verify-pending.timer
|
||||
```
|
||||
|
||||
Enable timers:
|
||||
|
||||
```bash
|
||||
|
||||
163
cron_tasks/verify_pending_external.py
Executable file
163
cron_tasks/verify_pending_external.py
Executable file
@@ -0,0 +1,163 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Verify pending (unconfirmed) engrams using lightweight external checks.
|
||||
|
||||
Policy (conservative):
|
||||
- `openclaw-memory` is treated as internal ground-truth and is auto-confirmed
|
||||
by the review job (see `cron_tasks/review_brain.py` in the workspace runtime).
|
||||
- For `source=web`, confirm if the grounded URL responds with HTTP 2xx, reject on
|
||||
4xx/5xx, and keep pending on timeouts/unknown.
|
||||
- Reject obvious low-signal placeholders (e.g. session summary stubs).
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from datetime import datetime, timezone
|
||||
from typing import Any, Optional
|
||||
|
||||
|
||||
WORKSPACE = Path(os.environ.get("SECOND_BRAIN_WORKSPACE", "/root/.openclaw/workspace/second-brain"))
|
||||
DB_PATH = Path(os.environ.get("BRAIN_DB", str(WORKSPACE / "data" / "brain.sqlite"))).resolve()
|
||||
|
||||
sys.path.insert(0, str(WORKSPACE))
|
||||
from src.store import EngramStore
|
||||
from src.engram import ReviewEntry
|
||||
|
||||
OUTPUT_FILE = os.environ.get("CRON_OUTPUT_FILE", "/tmp/verify_pending_external.json")
|
||||
|
||||
|
||||
def _now() -> str:
|
||||
return datetime.now(timezone.utc).isoformat()
|
||||
|
||||
|
||||
def _get_url(meta: dict[str, Any]) -> Optional[str]:
|
||||
url = meta.get("url")
|
||||
if isinstance(url, str) and url.startswith(("http://", "https://")):
|
||||
return url
|
||||
grounding = meta.get("grounding")
|
||||
if isinstance(grounding, dict):
|
||||
g_url = grounding.get("url")
|
||||
if isinstance(g_url, str) and g_url.startswith(("http://", "https://")):
|
||||
return g_url
|
||||
return None
|
||||
|
||||
|
||||
def _http_status(url: str, timeout_s: float = 6.0) -> Optional[int]:
|
||||
try:
|
||||
import urllib.request
|
||||
|
||||
req = urllib.request.Request(
|
||||
url,
|
||||
method="GET",
|
||||
headers={"User-Agent": "openclaw-secondbrain/verify_pending_external"},
|
||||
)
|
||||
with urllib.request.urlopen(req, timeout=timeout_s) as resp:
|
||||
return int(getattr(resp, "status", 200))
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def main() -> int:
|
||||
if not DB_PATH.exists():
|
||||
out = {"success": False, "error": f"db missing: {DB_PATH}", "time": _now()}
|
||||
Path(OUTPUT_FILE).write_text(json.dumps(out, indent=2))
|
||||
print(out["error"])
|
||||
return 1
|
||||
|
||||
store = EngramStore(str(DB_PATH))
|
||||
all_egs = store.get_all()
|
||||
pending = [
|
||||
eg
|
||||
for eg in all_egs
|
||||
if (not eg.correctness.confirmed and eg.correctness.rejections == 0)
|
||||
]
|
||||
|
||||
confirmed = 0
|
||||
rejected = 0
|
||||
still_pending = 0
|
||||
checked = 0
|
||||
|
||||
for eg in pending:
|
||||
checked += 1
|
||||
src = eg.metadata.get("source")
|
||||
content = (eg.content or "").strip()
|
||||
|
||||
if src == "session" and (
|
||||
content.startswith("Session Summary (sess_") or content.startswith("Please remember ")
|
||||
):
|
||||
eg.correctness.rejections += 1
|
||||
eg.correctness.last_reviewed = _now()
|
||||
eg.correctness.review_history.append(
|
||||
ReviewEntry(
|
||||
by="verify-pending",
|
||||
action="reject",
|
||||
at=_now(),
|
||||
note="Auto-reject: session placeholder",
|
||||
)
|
||||
)
|
||||
store.save(eg)
|
||||
rejected += 1
|
||||
continue
|
||||
|
||||
if src == "web":
|
||||
url = _get_url(eg.metadata)
|
||||
if not url:
|
||||
still_pending += 1
|
||||
continue
|
||||
status = _http_status(url)
|
||||
if status is None:
|
||||
still_pending += 1
|
||||
continue
|
||||
if 200 <= status < 300:
|
||||
eg.correctness.confirmed = True
|
||||
eg.correctness.confirmations += 1
|
||||
eg.correctness.last_reviewed = _now()
|
||||
eg.correctness.review_history.append(
|
||||
ReviewEntry(
|
||||
by="verify-pending",
|
||||
action="confirm",
|
||||
at=_now(),
|
||||
note=f"Auto-confirm: web url ok ({status}) {url}",
|
||||
)
|
||||
)
|
||||
store.save(eg)
|
||||
confirmed += 1
|
||||
else:
|
||||
eg.correctness.rejections += 1
|
||||
eg.correctness.last_reviewed = _now()
|
||||
eg.correctness.review_history.append(
|
||||
ReviewEntry(
|
||||
by="verify-pending",
|
||||
action="reject",
|
||||
at=_now(),
|
||||
note=f"Auto-reject: web url status={status} {url}",
|
||||
)
|
||||
)
|
||||
store.save(eg)
|
||||
rejected += 1
|
||||
continue
|
||||
|
||||
still_pending += 1
|
||||
|
||||
out = {
|
||||
"success": True,
|
||||
"time": _now(),
|
||||
"total": len(all_egs),
|
||||
"pending_before": len(pending),
|
||||
"checked": checked,
|
||||
"confirmed": confirmed,
|
||||
"rejected": rejected,
|
||||
"still_pending": still_pending,
|
||||
}
|
||||
Path(OUTPUT_FILE).write_text(json.dumps(out, indent=2))
|
||||
print(
|
||||
f"VERIFY: pending_before={out['pending_before']} confirmed={confirmed} rejected={rejected} still_pending={still_pending}"
|
||||
)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
|
||||
@@ -31,6 +31,14 @@ sudo ln -sf /root/.openclaw/workspace/second-brain/systemd/openclaw-secondbrain-
|
||||
sudo systemctl daemon-reload
|
||||
```
|
||||
|
||||
Optional (verification hardening):
|
||||
|
||||
```bash
|
||||
sudo ln -sf /root/.openclaw/workspace/second-brain/systemd/openclaw-secondbrain-verify-pending.* /etc/systemd/system/
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable --now openclaw-secondbrain-verify-pending.timer
|
||||
```
|
||||
|
||||
### Enable timers
|
||||
|
||||
```bash
|
||||
|
||||
9
systemd/openclaw-secondbrain-verify-pending.service
Normal file
9
systemd/openclaw-secondbrain-verify-pending.service
Normal file
@@ -0,0 +1,9 @@
|
||||
[Unit]
|
||||
Description=OpenClaw Second-Brain verify_pending_external
|
||||
OnFailure=openclaw-secondbrain-notify@%n.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
WorkingDirectory=/root/.openclaw/workspace
|
||||
ExecStart=/bin/bash -lc 'flock -n /tmp/%n.lock /usr/bin/python3 /root/.openclaw/workspace/openclaw_cron_wrapper.py verify_pending_external'
|
||||
|
||||
11
systemd/openclaw-secondbrain-verify-pending.timer
Normal file
11
systemd/openclaw-secondbrain-verify-pending.timer
Normal file
@@ -0,0 +1,11 @@
|
||||
[Unit]
|
||||
Description=OpenClaw Second-Brain periodic verify_pending_external
|
||||
|
||||
[Timer]
|
||||
OnBootSec=15min
|
||||
OnUnitActiveSec=2h
|
||||
Persistent=true
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
|
||||
Reference in New Issue
Block a user