diff --git a/scripts/ops/hermes_triage_monitor.py b/scripts/ops/hermes_triage_monitor.py index 170f155ed..452dba36b 100755 --- a/scripts/ops/hermes_triage_monitor.py +++ b/scripts/ops/hermes_triage_monitor.py @@ -40,6 +40,10 @@ GRAFANA = os.environ.get("GRAFANA_URL", "https://metrics.bstein.dev") HERMES_UI = os.environ.get("HERMES_URL", "https://agent.bstein.dev") POLL_SECONDS = 6 +# The fixture job repairs a ConfigMap; the code job proposes a patch. Evidence +# that suits one is false for the other, so the stages branch on it. +IS_CODE_JOB = JOB == "hermes-code-demo" + BOLD, DIM, GREEN, CYAN, YELLOW, RED, RESET = ( "\033[1m", "\033[2m", "\033[32m", "\033[36m", "\033[33m", "\033[31m", "\033[0m" ) @@ -84,7 +88,8 @@ STAGES: dict[str, tuple[str, str, str, str]] = { ), "verify": ( "Ariadne response", - "One rebuild decides whether the repair held", + "The branch build checks the proposal" if JOB == "hermes-code-demo" + else "One rebuild decides whether the repair held", "Action result -> validation build", f"{JENKINS}/job/{JOB}/ — a new build starts on its own", ), @@ -299,15 +304,25 @@ def evidence_for(key: str, incident: str = "") -> None: "printenv", "ARIADNE_HERMES_MIN_CONFIDENCE"], limit=2) print() elif key == "route": - print(f" {DIM}the fixture repair is an operational action, so the Optional source" - f" proposal branch is not taken for this incident{RESET}\n") + if IS_CODE_JOB: + print(f" {DIM}a source fix is not one of the registered actions, so this takes" + f" the Optional source proposal branch rather than the Action registry.{RESET}\n") + else: + print(f" {DIM}the fixture repair is an operational action, so the Optional source" + f" proposal branch is not taken for this incident{RESET}\n") elif key in {"response", "outputs"}: - run(["kubectl", "-n", NS_DEMO, "get", "cm", "hermes-triage-demo-fixture", - "-o", "jsonpath={.data.state}"]) - if key == "response": - print(f" {DIM}that value read 'unhealthy' when the build failed - the seeded" - f" fault - and reads 'healthy' above because Ariadne has just patched it." - f" That single field changing is the repair.{RESET}\n") + if IS_CODE_JOB: + print(f" {DIM}the pull request Ariadne opened is recorded on the incident above" + f" (branch, pr_number, url). Hermes produced the patch as data; Ariadne" + f" validated it and pushed the branch.{RESET}") + print(f" {YELLOW}pull requests: {GITEA}/bstein/hermes-code-demo/pulls{RESET}\n") + else: + run(["kubectl", "-n", NS_DEMO, "get", "cm", "hermes-triage-demo-fixture", + "-o", "jsonpath={.data.state}"]) + if key == "response": + print(f" {DIM}that value read 'unhealthy' when the build failed - the seeded" + f" fault - and reads 'healthy' above because Ariadne has just patched" + f" it. That single field changing is the repair.{RESET}\n") if key == "outputs": print(f" {DIM}on the chart this is the 'records and artifacts' edge out of the" f" whole Ariadne response box, not out of one branch. Every path ends" @@ -315,10 +330,15 @@ def evidence_for(key: str, incident: str = "") -> None: f" the same audit events and metrics.{RESET}") print(f" {YELLOW}issues filed by triage: {GITEA}/bstein/ariadne/issues{RESET}\n") elif key == "verify": - print(f" {DIM}exactly one rebuild is triggered; it never retries in a loop. This" - f" completes the operational branch: because the action was authorized and" - f" performed, neither the human-required response nor the optional source" - f" proposal is entered for this incident.{RESET}\n") + if IS_CODE_JOB: + print(f" {DIM}the branch build validates the proposal. Nothing merges" + f" automatically: the incident stays human-required whatever the branch" + f" build says, because a person decides whether the fix is right.{RESET}\n") + else: + print(f" {DIM}exactly one rebuild is triggered; it never retries in a loop. This" + f" completes the operational branch: because the action was authorized and" + f" performed, neither the human-required response nor the optional source" + f" proposal is entered for this incident.{RESET}\n") class Monitor: