fix(work): import hashlib and wire heal subparser into main CLI

This commit is contained in:
operator
2026-10-09 23:13:43 +00:00
parent c3b4b1cd28
commit f75977ca6e
202 changed files with 4185 additions and 4142 deletions
+51 -12
View File
@@ -364,12 +364,11 @@ DM_LOG_FILE = os.path.join(NETVM_ROOT, "dm-log.jsonl")
JOB_LOG_FILE = os.path.join(NETVM_ROOT, "job-log.jsonl")
def reconstruct_loops(limit=50, agent=None, status_filter=None) -> list:
"""Reconstruct active and recent loops from followups.json and dm-log.jsonl.
def _load_loop_candidates() -> dict:
"""Parse followups.json + dm-log.jsonl into a loop_id -> dict map.
Returns a list of dicts:
loop_id, agent, sender, target, purpose, state, sent_at, deadline,
nudges_sent, nudges_allowed, escalate_to, tags, summary
Pure parse phase of reconstruct_loops, extracted so diagnose_breaks and
remediate_breaks can share one parse instead of re-reading the logs.
"""
loops = {} # loop_id -> dict
@@ -499,6 +498,11 @@ def reconstruct_loops(limit=50, agent=None, status_filter=None) -> list:
"source": "dm-log.jsonl",
}
return loops
def _select_loops(loops: dict, limit=50, agent=None, status_filter=None) -> list:
"""Filter/sort/limit a candidate map from _load_loop_candidates."""
# Filter and sort
result = list(loops.values())
if agent:
@@ -517,6 +521,17 @@ def reconstruct_loops(limit=50, agent=None, status_filter=None) -> list:
return result[:limit]
def reconstruct_loops(limit=50, agent=None, status_filter=None) -> list:
"""Reconstruct active and recent loops from followups.json and dm-log.jsonl.
Returns a list of dicts:
loop_id, agent, sender, target, purpose, state, sent_at, deadline,
nudges_sent, nudges_allowed, escalate_to, tags, summary
"""
return _select_loops(_load_loop_candidates(), limit=limit, agent=agent,
status_filter=status_filter)
def get_fleet_loop_health(threshold=None) -> dict:
"""Calculate fleet loop health per agent and overall verdict."""
if threshold is None:
@@ -570,8 +585,14 @@ def get_fleet_loop_health(threshold=None) -> dict:
}
def diagnose_breaks() -> list:
"""Diagnose break taxonomy across intrinsic loops and support services."""
def diagnose_breaks(_fleet_cache=None, _loops_cache=None) -> list:
"""Diagnose break taxonomy across intrinsic loops and support services.
_fleet_cache: optional list; when given, the fleet approval scan result
is appended so callers (remediate_breaks) can reuse it instead of
re-scanning (each scan fans 6 nodes over the full audit log).
_loops_cache: optional list; when given, the parsed loop-candidate map
is appended for the same single-parse sharing."""
import subprocess
breaks = []
@@ -609,7 +630,10 @@ def diagnose_breaks() -> list:
})
# 3. Active follow-up loops check
active_loops = reconstruct_loops(limit=20, status_filter="pending")
_loops_map = _load_loop_candidates()
if _loops_cache is not None:
_loops_cache.append(_loops_map)
active_loops = _select_loops(_loops_map, limit=20, status_filter="pending")
now_ts = time.time()
for l in active_loops:
nudges_sent = l.get("nudges_sent", 0)
@@ -628,6 +652,8 @@ def diagnose_breaks() -> list:
try:
import approvals
fleet_apps = approvals.check_fleet_approvals()
if _fleet_cache is not None:
_fleet_cache.append(fleet_apps)
for app in fleet_apps:
if app.get("has_pending"):
node = app["node"]
@@ -734,7 +760,9 @@ def remediate_breaks(dry_run=False) -> dict:
escalated = []
# 1. Check diagnosed hard breaks first
breaks = diagnose_breaks()
_fleet_cache = []
_loops_cache = []
breaks = diagnose_breaks(_fleet_cache=_fleet_cache, _loops_cache=_loops_cache)
for b in breaks:
if b.get("severity") in ("CRITICAL", "WARNING"):
escalated.append(b)
@@ -753,8 +781,13 @@ def remediate_breaks(dry_run=False) -> dict:
now_iso = datetime.now(timezone.utc).isoformat()
# Build answer map from reconstruct_loops
loops = reconstruct_loops(limit=200)
# Build answer map from reconstruct_loops (reuse diagnose's parse:
# nothing between the parses writes the loop logs in-process, and a
# concurrently landed reply is picked up on the next cycle).
if _loops_cache:
loops = _select_loops(_loops_cache[0], limit=200)
else:
loops = reconstruct_loops(limit=200)
answered_dms = {
l["loop_id"]: l for l in loops if l.get("state") in ("ANSWERED", "CLOSED")
}
@@ -836,7 +869,13 @@ def remediate_breaks(dry_run=False) -> dict:
# Auto-remediate trusted approval blocks
try:
import approvals
fleet_apps = approvals.check_fleet_approvals()
# Reuse the diagnose_breaks scan: nothing between the scans touches
# browser-approval state, and this block only reads it. Fall back to
# a fresh scan if the first one failed.
if _fleet_cache:
fleet_apps = _fleet_cache[0]
else:
fleet_apps = approvals.check_fleet_approvals()
for app in fleet_apps:
if app.get("has_pending") and app.get("is_trusted") and app.get("status") != "KEY_APPROVAL":
node = app["node"]