no-mistakes(review): Pin Mumuni removal behaviorally and fix digest import bug
This commit is contained in:
@@ -679,6 +679,6 @@ if __name__ == "__main__":
|
|||||||
print(f" Zulip Ext: {'✅' if report.get('zulip_ext',{}).get('connected') else '❌'}")
|
print(f" Zulip Ext: {'✅' if report.get('zulip_ext',{}).get('connected') else '❌'}")
|
||||||
print(f" LiteLLM: {sum(1 for c in report.get('litellm',{}).get('checks',[]) if c['status']=='pass')}/{len(report.get('litellm',{}).get('checks',[]))} checks pass")
|
print(f" LiteLLM: {sum(1 for c in report.get('litellm',{}).get('checks',[]) if c['status']=='pass')}/{len(report.get('litellm',{}).get('checks',[]))} checks pass")
|
||||||
agent_parts = []
|
agent_parts = []
|
||||||
for k,v in report.get('agents',{}).items():
|
for k,v in report.get('agents',{}).items():
|
||||||
agent_parts.append(f"{k}:{v.get('gateway_state',v.get('pm2_status','?'))}")
|
agent_parts.append(f"{k}:{v.get('gateway_state',v.get('pm2_status','?'))}")
|
||||||
print(f" Agents: {', '.join(agent_parts)}")
|
print(f" Agents: {', '.join(agent_parts)}")
|
||||||
|
|||||||
@@ -21,10 +21,13 @@ CONTRACT UNDER TEST:
|
|||||||
* `zulip-health.prose.md` retires the Mumuni-only steps and says explicitly
|
* `zulip-health.prose.md` retires the Mumuni-only steps and says explicitly
|
||||||
that Mumuni is not monitored from this host.
|
that Mumuni is not monitored from this host.
|
||||||
|
|
||||||
HOW: structural greps plus a behavioral sandbox. The sandbox copies the shipped
|
HOW: behavioral execution plus one named deliverable-text contract. The sandbox
|
||||||
script verbatim and rewrites only its LOG constant, then runs it with stub
|
copies the shipped monitor verbatim and rewrites only its LOG constant, then
|
||||||
ssh/curl on PATH. The ssh stub records every host it is asked to reach, so
|
runs it with stub ssh/curl on PATH; the ssh stub records every host it is asked
|
||||||
"never probes .24" is asserted from observed behavior, not from source text.
|
to reach, so "never probes .24" and "no Mumuni notify" are asserted from
|
||||||
|
observed behavior. The daily digest is pinned by importing it and exercising
|
||||||
|
collect() and build_html() directly. The single source-text assertion is the
|
||||||
|
deliverable-text contract the captain acceptance names for the shipped monitor.
|
||||||
|
|
||||||
Usage: python3 -m pytest tests/test_mumuni_monitor_removal.py
|
Usage: python3 -m pytest tests/test_mumuni_monitor_removal.py
|
||||||
"""
|
"""
|
||||||
@@ -50,26 +53,19 @@ TANKO_VANTAGE = "192.168.68.15" # amdpve — Tanko CT 112 via pct exec
|
|||||||
AGENT_ZERO_HOST = "192.168.68.14" # kagentz host, Agent Zero docker
|
AGENT_ZERO_HOST = "192.168.68.14" # kagentz host, Agent Zero docker
|
||||||
|
|
||||||
|
|
||||||
# ── scripts/zulip-monitor.sh: structural guards ──────────────────────
|
# ── scripts/zulip-monitor.sh: deliverable-text contract ─────────────
|
||||||
|
|
||||||
def test_zulip_monitor_has_no_mumuni_reference():
|
def test_zulip_monitor_deliverable_text_contract():
|
||||||
|
"""Owned deliverable-text contract for scripts/zulip-monitor.sh.
|
||||||
|
|
||||||
|
Captain acceptance requires the shipped monitor to contain no Mumuni probe
|
||||||
|
identifier and no 192.168.68.24 literal. Behavioral proof that the monitor
|
||||||
|
never contacts that host and never emits a Mumuni notify lives in the
|
||||||
|
sandbox tests below; this only pins the named text contract.
|
||||||
|
"""
|
||||||
text = ZULIP_MONITOR.read_text()
|
text = ZULIP_MONITOR.read_text()
|
||||||
assert "mumuni" not in text.lower()
|
assert "mumuni" not in text.lower()
|
||||||
assert "gateway_state.json" not in text
|
assert MUMUNI_IP not in text
|
||||||
|
|
||||||
|
|
||||||
def test_zulip_monitor_has_no_24_reference():
|
|
||||||
assert MUMUNI_IP not in ZULIP_MONITOR.read_text()
|
|
||||||
|
|
||||||
|
|
||||||
def test_zulip_monitor_keeps_bridge_tanko_and_agent_zero_legs():
|
|
||||||
text = ZULIP_MONITOR.read_text()
|
|
||||||
assert "Platform A: pi (Abiba)" in text # the Zulip bridge
|
|
||||||
assert "Platform B: Tanko" in text
|
|
||||||
assert "Platform C: Agent Zero" in text
|
|
||||||
assert TANKO_VANTAGE in text
|
|
||||||
assert AGENT_ZERO_HOST in text
|
|
||||||
assert "kagentz" in text
|
|
||||||
|
|
||||||
|
|
||||||
# ── scripts/zulip-monitor.sh: behavioral sandbox ─────────────────────
|
# ── scripts/zulip-monitor.sh: behavioral sandbox ─────────────────────
|
||||||
@@ -218,26 +214,104 @@ def test_failing_run_alerts_on_tanko_but_never_on_mumuni(tmp_path):
|
|||||||
assert "Result: 🔴 1 issue(s) found" in log
|
assert "Result: 🔴 1 issue(s) found" in log
|
||||||
|
|
||||||
|
|
||||||
# ── scripts/daily-infra-report.py: no Mumuni agent probe ─────────────
|
# ── scripts/daily-infra-report.py: behavioral digest checks ──────────
|
||||||
|
|
||||||
def test_daily_report_has_no_mumuni_agent_probe():
|
@pytest.fixture(scope="module")
|
||||||
text = DAILY_REPORT.read_text()
|
def daily():
|
||||||
assert 'report["agents"]["mumuni"]' not in text
|
spec = importlib.util.spec_from_file_location("daily_infra_report", DAILY_REPORT)
|
||||||
assert f'ssh("{MUMUNI_IP}"' not in text
|
assert spec and spec.loader
|
||||||
assert "hermes --version" not in text
|
module = importlib.util.module_from_spec(spec)
|
||||||
|
spec.loader.exec_module(module)
|
||||||
|
return module
|
||||||
|
|
||||||
|
|
||||||
def test_daily_report_keeps_abiba_and_tanko_agent_legs():
|
DAILY_AGENTS = {
|
||||||
text = DAILY_REPORT.read_text()
|
"abiba": {
|
||||||
assert 'report["agents"]["abiba"]' in text
|
"platform": "pi", "ct": 100, "ip": MUMUNI_IP,
|
||||||
assert 'report["agents"]["tanko"]' in text
|
"zulip_connected": True, "zulip_processed": 5,
|
||||||
|
"pm2_status": "online", "pm2_restarts": "0", "pm2_uptime": "1h",
|
||||||
|
},
|
||||||
|
"tanko": {
|
||||||
|
"platform": "dsh", "ct": 112, "ip": "192.168.68.122",
|
||||||
|
"gateway_state": "n/a (DSH)", "zulip_state": "connected",
|
||||||
|
"telegram_state": "unknown", "gateway_pid": None, "updated_at": "",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def test_daily_report_still_describes_abiba_at_its_own_ct100_ip():
|
def _fabricated_report(agents):
|
||||||
# .24 is abiba's own CT 100 address — the IP itself is legitimate; only a
|
return {
|
||||||
# Mumuni gateway probe against it was the fault.
|
"nodes": {},
|
||||||
assert '"platform": "pi", "ct": 100, "ip": "192.168.68.24"' in \
|
"node_count": 1,
|
||||||
DAILY_REPORT.read_text()
|
"nodes_online": 1,
|
||||||
|
"total_vms": 0,
|
||||||
|
"running_vms": 0,
|
||||||
|
"stopped_vms": [],
|
||||||
|
"vms_by_node": {n: [] for n in
|
||||||
|
["amdpve", "minipve", "storepve", "acerpve", "ocupve"]},
|
||||||
|
"storage": [],
|
||||||
|
"docker_vm": {"total": 0, "running": 0, "unhealthy": [],
|
||||||
|
"containers": [], "reclaimable": "", "disk_used": "1%"},
|
||||||
|
"docker_syslog": {"total": 0, "running": 0, "containers": []},
|
||||||
|
"docker_netbird": {"total": 0, "running": 0, "containers": []},
|
||||||
|
"endpoints": [],
|
||||||
|
"litellm": {"checks": []},
|
||||||
|
"nfs": [],
|
||||||
|
"zulip_ext": {
|
||||||
|
"connected": True, "queue_id": "queue", "last_error": None,
|
||||||
|
"messages_processed": 0, "retry_count": 0, "pm2": {},
|
||||||
|
"pm2_healthy": True, "bot_skipped_15min": 0, "finalized_1h": 0,
|
||||||
|
"failed_finalize_1h": 0, "finalize_fail_pct": 0,
|
||||||
|
"server_status": "200",
|
||||||
|
},
|
||||||
|
"agents": agents,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _agent_status_card(html):
|
||||||
|
start = html.index("🤖 Agent Status")
|
||||||
|
end = html.index("💬 Zulip Extension")
|
||||||
|
return html[start:end]
|
||||||
|
|
||||||
|
|
||||||
|
def test_daily_report_renders_only_abiba_and_tanko_agents(daily):
|
||||||
|
"""build_html() over a Mumuni-free agent set must render no Mumuni row and
|
||||||
|
no Mumuni gateway-unknown issue, while abiba and tanko rows still render."""
|
||||||
|
html = daily.build_html(_fabricated_report(dict(DAILY_AGENTS)))
|
||||||
|
card = _agent_status_card(html)
|
||||||
|
assert "mumuni" not in card.lower()
|
||||||
|
assert "abiba" in card
|
||||||
|
assert "tanko" in card
|
||||||
|
assert "mumuni" not in html.lower()
|
||||||
|
|
||||||
|
|
||||||
|
def test_daily_report_collect_never_probes_mumuni(monkeypatch, daily):
|
||||||
|
"""collect() with ssh stubbed must add no mumuni agent and must never ssh
|
||||||
|
its decommissioned .24 host."""
|
||||||
|
probed = []
|
||||||
|
|
||||||
|
class _NoSubprocess:
|
||||||
|
@staticmethod
|
||||||
|
def check_output(*args, **kwargs):
|
||||||
|
return b""
|
||||||
|
|
||||||
|
def fake_ssh(host, cmd):
|
||||||
|
probed.append(host)
|
||||||
|
return ""
|
||||||
|
|
||||||
|
monkeypatch.setattr(daily, "pve_get", lambda path: [])
|
||||||
|
monkeypatch.setattr(daily, "ssh_jerome", lambda host, cmd: "")
|
||||||
|
monkeypatch.setattr(daily, "ssh", fake_ssh)
|
||||||
|
monkeypatch.setattr(daily, "http_get",
|
||||||
|
lambda url, auth=None, timeout=10: "200")
|
||||||
|
monkeypatch.setattr(daily, "http_get_body",
|
||||||
|
lambda url, auth=None, timeout=10: "")
|
||||||
|
monkeypatch.setattr(daily, "count_in_log", lambda *a, **k: 0)
|
||||||
|
monkeypatch.setattr(daily, "subprocess", _NoSubprocess)
|
||||||
|
|
||||||
|
report = daily.collect()
|
||||||
|
assert "mumuni" not in report["agents"]
|
||||||
|
assert MUMUNI_IP not in probed
|
||||||
|
|
||||||
|
|
||||||
# ── scripts/agent-health-check.py: roster pin ───────────────────────
|
# ── scripts/agent-health-check.py: roster pin ───────────────────────
|
||||||
@@ -255,12 +329,6 @@ def test_agent_health_roster_has_no_mumuni_entry(ahc):
|
|||||||
assert "mumuni" not in ahc.AGENTS
|
assert "mumuni" not in ahc.AGENTS
|
||||||
|
|
||||||
|
|
||||||
def test_agent_health_roster_comment_no_longer_places_mumuni_at_24():
|
|
||||||
text = AHC.read_text()
|
|
||||||
assert "mumuni (.24" not in text
|
|
||||||
assert "mumuni (.24, inside abiba CT100)" not in text
|
|
||||||
|
|
||||||
|
|
||||||
# ── zulip-health.prose.md: contract reconciliation ──────────────────
|
# ── zulip-health.prose.md: contract reconciliation ──────────────────
|
||||||
|
|
||||||
def test_health_contract_retires_mumuni_only_steps():
|
def test_health_contract_retires_mumuni_only_steps():
|
||||||
|
|||||||
Reference in New Issue
Block a user