fix(demo): make the monitor's evidence correct for the code demo too
Some checks failed
Tests / Declarative: Post Actions testing.tests.test_repo_structure.test_knowledge_service_mirror_matches_source failed

Several stages assumed the fixture job. On a code-demo run they would have
read the fixture ConfigMap, which is unrelated to that job, and asserted that
a field changing from unhealthy to healthy was the repair - flatly false when
the outcome is a pull request. The route stage would also have claimed the
source-proposal branch was not taken during the run that takes it.

The stages now branch on the job: the route explains that a source fix is not
a registered action and so takes the proposal branch; the response points at
the pull request recorded on the incident; and the verify stage says the
branch build validates the proposal and that nothing merges without a human
whatever it reports.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
jenkins 2026-08-06 20:07:10 -03:00
parent 4ffcae8b3c
commit 4fe4162dad

View File

@ -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") HERMES_UI = os.environ.get("HERMES_URL", "https://agent.bstein.dev")
POLL_SECONDS = 6 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 = ( BOLD, DIM, GREEN, CYAN, YELLOW, RED, RESET = (
"\033[1m", "\033[2m", "\033[32m", "\033[36m", "\033[33m", "\033[31m", "\033[0m" "\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": ( "verify": (
"Ariadne response", "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", "Action result -> validation build",
f"{JENKINS}/job/{JOB}/ — a new build starts on its own", 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) "printenv", "ARIADNE_HERMES_MIN_CONFIDENCE"], limit=2)
print() print()
elif key == "route": elif key == "route":
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" 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") f" proposal branch is not taken for this incident{RESET}\n")
elif key in {"response", "outputs"}: elif key in {"response", "outputs"}:
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", run(["kubectl", "-n", NS_DEMO, "get", "cm", "hermes-triage-demo-fixture",
"-o", "jsonpath={.data.state}"]) "-o", "jsonpath={.data.state}"])
if key == "response": if key == "response":
print(f" {DIM}that value read 'unhealthy' when the build failed - the seeded" 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" fault - and reads 'healthy' above because Ariadne has just patched"
f" That single field changing is the repair.{RESET}\n") f" it. That single field changing is the repair.{RESET}\n")
if key == "outputs": if key == "outputs":
print(f" {DIM}on the chart this is the 'records and artifacts' edge out of the" 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" f" whole Ariadne response box, not out of one branch. Every path ends"
@ -315,6 +330,11 @@ def evidence_for(key: str, incident: str = "") -> None:
f" the same audit events and metrics.{RESET}") f" the same audit events and metrics.{RESET}")
print(f" {YELLOW}issues filed by triage: {GITEA}/bstein/ariadne/issues{RESET}\n") print(f" {YELLOW}issues filed by triage: {GITEA}/bstein/ariadne/issues{RESET}\n")
elif key == "verify": elif key == "verify":
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" 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" completes the operational branch: because the action was authorized and"
f" performed, neither the human-required response nor the optional source" f" performed, neither the human-required response nor the optional source"