test(update): trim marker-discharge tests to two invariants; document the identity rule

The five #105417 tests collapse into one positive (fleet current at expected_sha
discharges the marker) and one parametrized negative (stale row / empty probe /
unknown identity / checkout moved past the marker keep the warning). Both are red
on origin/main. collect_fleet_versions' docstring now names why a live PID alone
is not a `current` row (#110420): write_runtime_status re-stamps pid/code_sha for
whatever process writes it, so the state-file fallback must pass
live_gateway_pid_for_home like the inventory already does (#109680).
This commit is contained in:
teknium1
2026-09-14 18:05:50 -07:00
committed by Teknium
parent 8130274b37
commit 2fcb50c50e
2 changed files with 25 additions and 77 deletions
+4 -1
View File
@@ -287,7 +287,10 @@ def collect_fleet_versions(*, pre_restart_pids: Optional[list[int]] = None) -> l
``stale`` — gateway stamped a code_sha that differs from the updated checkout's HEAD (it is still
serving pre-update modules). ``unknown`` — gateway predates the code-identity stamp (started before this
feature landed) or identity could not be resolved. ``down`` — the gateway was ALIVE when this update
feature landed), identity could not be resolved, or the state file's live PID is not the
verified gateway for that home (``live_gateway_pid_for_home``): ``write_runtime_status`` re-stamps
``pid``/``code_sha`` for whatever process writes it, so a foreign writer must never read as
``current`` (#110420, sibling of #109680). ``down`` — the gateway was ALIVE when this update
started (``pre_restart_pids``), its runtime status still says running, but the PID is dead and no
successor rewrote the record: the restart phase stopped it and nothing came back. Without this row a
killed-and-never-replaced gateway produced NO entry at all and the matrix passed silently (Phase-1
@@ -611,12 +611,12 @@ def test_startup_warn_silent_when_nothing_pending(capsys):
assert captured.out == ""
# ── Self-heal: marker left behind by a supervisor-level restart (TRA-1180 class) ──
# ── Self-heal: marker left behind by a supervisor-level restart (#105417 / #111272) ──
#
# `systemctl --user restart hermes-gateway` (weekly-update fallback, manual ops) never
# runs this module's clear path, so the marker survives a restart that DID bring the
# fleet to the pulled code — and every later CLI call warns forever. The marker must be
# discharged when (and only when) the fleet provably serves expected_sha.
# `systemctl --user restart hermes-gateway` never runs this module's clear path, and an update
# whose fleet probe answered empty exits before clearing — so the marker survives a restart
# that DID bring the fleet to the pulled code, and every later CLI call warns forever. The
# marker is discharged when (and only when) the fleet provably serves expected_sha.
def _patch_marker_sha(monkeypatch, disk_sha):
@@ -628,11 +628,6 @@ def test_startup_warn_discharged_when_fleet_current(monkeypatch, capsys):
disk_sha = "e" * 40
update_cmd._write_fleet_restart_pending_marker(expected_sha=disk_sha)
_patch_marker_sha(monkeypatch, disk_sha)
monkeypatch.setattr(
update_cmd_fleet,
"_marker_only_restart_obsolete",
update_cmd_fleet._marker_only_restart_obsolete,
)
monkeypatch.setattr(
"hermes_cli.update_receipt.collect_fleet_versions",
lambda **kwargs: [
@@ -642,77 +637,27 @@ def test_startup_warn_discharged_when_fleet_current(monkeypatch, capsys):
update_cmd._warn_pending_fleet_restart_on_startup()
captured = capsys.readouterr()
assert captured.err == ""
assert capsys.readouterr().err == ""
assert not update_cmd._fleet_restart_pending_marker_path().exists()
def test_startup_warn_kept_when_fleet_stale(monkeypatch, capsys):
disk_sha = "e" * 40
update_cmd._write_fleet_restart_pending_marker(expected_sha=disk_sha)
@pytest.mark.parametrize(
"disk_sha, fleet",
[
("e" * 40, [{"profile": "default", "pid": 42, "code_sha": "7" * 40, "code_version": "0.20.0", "state": "stale"}]),
("e" * 40, []), # probe answered empty: no proof either way
("e" * 40, [{"profile": "default", "pid": 42, "code_sha": None, "code_version": None, "state": "unknown"}]),
# checkout advanced past the marker: a newer pull owns a fresh obligation
("f" * 40, [{"profile": "default", "pid": 42, "code_sha": "e" * 40, "code_version": None, "state": "current"}]),
],
ids=["stale-row", "empty-probe", "unknown-identity", "checkout-moved"],
)
def test_startup_warn_kept_without_positive_evidence(monkeypatch, capsys, disk_sha, fleet):
update_cmd._write_fleet_restart_pending_marker(expected_sha="e" * 40)
_patch_marker_sha(monkeypatch, disk_sha)
monkeypatch.setattr(
"hermes_cli.update_receipt.collect_fleet_versions",
lambda **kwargs: [
{"profile": "default", "pid": 42, "code_sha": "7" * 40, "code_version": "0.20.0", "state": "stale"}
],
)
monkeypatch.setattr("hermes_cli.update_receipt.collect_fleet_versions", lambda **kwargs: fleet)
update_cmd._warn_pending_fleet_restart_on_startup()
err = capsys.readouterr().err
assert "did not restart running gateways" in err
assert "did not restart running gateways" in capsys.readouterr().err
assert update_cmd._fleet_restart_pending_marker_path().exists()
def test_startup_warn_kept_when_fleet_probe_empty(monkeypatch, capsys):
disk_sha = "e" * 40
update_cmd._write_fleet_restart_pending_marker(expected_sha=disk_sha)
_patch_marker_sha(monkeypatch, disk_sha)
monkeypatch.setattr(
"hermes_cli.update_receipt.collect_fleet_versions",
lambda **kwargs: [],
)
update_cmd._warn_pending_fleet_restart_on_startup()
err = capsys.readouterr().err
assert "did not restart running gateways" in err
assert update_cmd._fleet_restart_pending_marker_path().exists()
def test_startup_warn_kept_when_fleet_identity_unknown(monkeypatch, capsys):
disk_sha = "e" * 40
update_cmd._write_fleet_restart_pending_marker(expected_sha=disk_sha)
_patch_marker_sha(monkeypatch, disk_sha)
monkeypatch.setattr(
"hermes_cli.update_receipt.collect_fleet_versions",
lambda **kwargs: [
{"profile": "default", "pid": 42, "code_sha": None, "code_version": None, "state": "unknown"}
],
)
update_cmd._warn_pending_fleet_restart_on_startup()
err = capsys.readouterr().err
assert "did not restart running gateways" in err
assert update_cmd._fleet_restart_pending_marker_path().exists()
def test_marker_kept_when_newer_pull_moved_checkout_past_marker(monkeypatch, capsys):
update_cmd._write_fleet_restart_pending_marker(expected_sha="d" * 40)
_patch_marker_sha(monkeypatch, "e" * 40) # checkout advanced after the marker
seen = {"called": False}
def _collect(**kwargs):
seen["called"] = True
return [{"profile": "default", "pid": 42, "code_sha": "d" * 40, "code_version": None, "state": "current"}]
monkeypatch.setattr("hermes_cli.update_receipt.collect_fleet_versions", _collect)
update_cmd._warn_pending_fleet_restart_on_startup()
err = capsys.readouterr().err
assert "did not restart running gateways" in err
assert update_cmd._fleet_restart_pending_marker_path().exists()
assert seen["called"] is False # short-circuits before probing the fleet